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_interface_utils.h>
16 #include <gtest/gtest.h>
17
18 #include <vector>
19
20 #include "src/StatsLogProcessor.h"
21 #include "src/stats_log_util.h"
22 #include "tests/statsd_test_util.h"
23
24 using ::ndk::SharedRefBase;
25
26 namespace android {
27 namespace os {
28 namespace statsd {
29
30 #ifdef __ANDROID__
31
32 namespace {
33
34 const int64_t metricId = 123456;
35
CreateStatsdConfig(bool useCondition=true)36 StatsdConfig CreateStatsdConfig(bool useCondition = true) {
37 StatsdConfig config;
38 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
39 auto pulledAtomMatcher =
40 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
41 *config.add_atom_matcher() = pulledAtomMatcher;
42 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
43 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
44
45 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
46 *config.add_predicate() = screenIsOffPredicate;
47
48 auto valueMetric = config.add_value_metric();
49 valueMetric->set_id(metricId);
50 valueMetric->set_what(pulledAtomMatcher.id());
51 if (useCondition) {
52 valueMetric->set_condition(screenIsOffPredicate.id());
53 }
54 *valueMetric->mutable_value_field() =
55 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
56 *valueMetric->mutable_dimensions_in_what() =
57 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
58 valueMetric->set_bucket(FIVE_MINUTES);
59 valueMetric->set_use_absolute_value_on_reset(true);
60 valueMetric->set_skip_zero_diff_output(false);
61 valueMetric->set_max_pull_delay_sec(INT_MAX);
62 valueMetric->set_split_bucket_for_app_upgrade(true);
63 valueMetric->set_min_bucket_size_nanos(1000);
64 return config;
65 }
66
CreateStatsdConfigWithStates()67 StatsdConfig CreateStatsdConfigWithStates() {
68 StatsdConfig config;
69 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
70
71 auto pulledAtomMatcher = CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
72 *config.add_atom_matcher() = pulledAtomMatcher;
73 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
74 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
75 *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
76 *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
77
78 auto screenOnPredicate = CreateScreenIsOnPredicate();
79 *config.add_predicate() = screenOnPredicate;
80
81 auto screenOffPredicate = CreateScreenIsOffPredicate();
82 *config.add_predicate() = screenOffPredicate;
83
84 auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
85 *config.add_predicate() = deviceUnpluggedPredicate;
86
87 auto screenOnOnBatteryPredicate = config.add_predicate();
88 screenOnOnBatteryPredicate->set_id(StringToId("screenOnOnBatteryPredicate"));
89 screenOnOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
90 addPredicateToPredicateCombination(screenOnPredicate, screenOnOnBatteryPredicate);
91 addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOnOnBatteryPredicate);
92
93 auto screenOffOnBatteryPredicate = config.add_predicate();
94 screenOffOnBatteryPredicate->set_id(StringToId("ScreenOffOnBattery"));
95 screenOffOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
96 addPredicateToPredicateCombination(screenOffPredicate, screenOffOnBatteryPredicate);
97 addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOffOnBatteryPredicate);
98
99 const State screenState =
100 CreateScreenStateWithSimpleOnOffMap(/*screen on id=*/321, /*screen off id=*/123);
101 *config.add_state() = screenState;
102
103 // ValueMetricSubsystemSleepWhileScreenOnOnBattery
104 auto valueMetric1 = config.add_value_metric();
105 valueMetric1->set_id(metricId);
106 valueMetric1->set_what(pulledAtomMatcher.id());
107 valueMetric1->set_condition(screenOnOnBatteryPredicate->id());
108 *valueMetric1->mutable_value_field() =
109 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
110 valueMetric1->set_bucket(FIVE_MINUTES);
111 valueMetric1->set_use_absolute_value_on_reset(true);
112 valueMetric1->set_skip_zero_diff_output(false);
113 valueMetric1->set_max_pull_delay_sec(INT_MAX);
114
115 // ValueMetricSubsystemSleepWhileScreenOffOnBattery
116 ValueMetric* valueMetric2 = config.add_value_metric();
117 valueMetric2->set_id(StringToId("ValueMetricSubsystemSleepWhileScreenOffOnBattery"));
118 valueMetric2->set_what(pulledAtomMatcher.id());
119 valueMetric2->set_condition(screenOffOnBatteryPredicate->id());
120 *valueMetric2->mutable_value_field() =
121 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
122 valueMetric2->set_bucket(FIVE_MINUTES);
123 valueMetric2->set_use_absolute_value_on_reset(true);
124 valueMetric2->set_skip_zero_diff_output(false);
125 valueMetric2->set_max_pull_delay_sec(INT_MAX);
126
127 // ValueMetricSubsystemSleepWhileOnBatterySliceScreen
128 ValueMetric* valueMetric3 = config.add_value_metric();
129 valueMetric3->set_id(StringToId("ValueMetricSubsystemSleepWhileOnBatterySliceScreen"));
130 valueMetric3->set_what(pulledAtomMatcher.id());
131 valueMetric3->set_condition(deviceUnpluggedPredicate.id());
132 *valueMetric3->mutable_value_field() =
133 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
134 valueMetric3->add_slice_by_state(screenState.id());
135 valueMetric3->set_bucket(FIVE_MINUTES);
136 valueMetric3->set_use_absolute_value_on_reset(true);
137 valueMetric3->set_skip_zero_diff_output(false);
138 valueMetric3->set_max_pull_delay_sec(INT_MAX);
139 return config;
140 }
141
142 } // namespace
143
144 /**
145 * Tests the initial condition and condition after the first log events for
146 * value metrics with either a combination condition or simple condition.
147 *
148 * Metrics should be initialized with condition kUnknown (given that the
149 * predicate is using the default InitialValue of UNKNOWN). The condition should
150 * be updated to either kFalse or kTrue if a condition event is logged for all
151 * children conditions.
152 */
TEST(ValueMetricE2eTest,TestInitialConditionChanges)153 TEST(ValueMetricE2eTest, TestInitialConditionChanges) {
154 StatsdConfig config = CreateStatsdConfigWithStates();
155 int64_t baseTimeNs = getElapsedRealtimeNs();
156 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
157 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
158
159 ConfigKey cfgKey;
160 int32_t tagId = util::SUBSYSTEM_SLEEP_STATE;
161 auto processor =
162 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
163 SharedRefBase::make<FakeSubsystemSleepCallback>(), tagId);
164
165 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
166 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
167 EXPECT_TRUE(metricsManager->isConfigValid());
168 EXPECT_EQ(3, metricsManager->mAllMetricProducers.size());
169
170 // Combination condition metric - screen on and device unplugged
171 sp<MetricProducer> metricProducer1 = metricsManager->mAllMetricProducers[0];
172 // Simple condition metric - device unplugged
173 sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[2];
174
175 EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
176 EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
177
178 auto screenOnEvent =
179 CreateScreenStateChangedEvent(configAddedTimeNs + 30, android::view::DISPLAY_STATE_ON);
180 processor->OnLogEvent(screenOnEvent.get());
181 EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
182 EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
183
184 auto screenOffEvent =
185 CreateScreenStateChangedEvent(configAddedTimeNs + 40, android::view::DISPLAY_STATE_OFF);
186 processor->OnLogEvent(screenOffEvent.get());
187 EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
188 EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
189
190 auto pluggedUsbEvent = CreateBatteryStateChangedEvent(
191 configAddedTimeNs + 50, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB);
192 processor->OnLogEvent(pluggedUsbEvent.get());
193 EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition);
194 EXPECT_EQ(ConditionState::kFalse, metricProducer2->mCondition);
195
196 auto pluggedNoneEvent = CreateBatteryStateChangedEvent(
197 configAddedTimeNs + 70, BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE);
198 processor->OnLogEvent(pluggedNoneEvent.get());
199 EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition);
200 EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition);
201 }
202
TEST(ValueMetricE2eTest,TestPulledEvents)203 TEST(ValueMetricE2eTest, TestPulledEvents) {
204 auto config = CreateStatsdConfig();
205 int64_t baseTimeNs = getElapsedRealtimeNs();
206 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
207 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
208
209 ConfigKey cfgKey;
210 auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
211 SharedRefBase::make<FakeSubsystemSleepCallback>(),
212 util::SUBSYSTEM_SLEEP_STATE);
213 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
214 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
215 processor->mPullerManager->ForceClearPullerCache();
216
217 int startBucketNum = processor->mMetricsManagers.begin()
218 ->second->mAllMetricProducers[0]
219 ->getCurrentBucketNum();
220 EXPECT_GT(startBucketNum, (int64_t)0);
221
222 // When creating the config, the value metric producer should register the alarm at the
223 // end of the current bucket.
224 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
225 EXPECT_EQ(bucketSizeNs,
226 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
227 int64_t& expectedPullTimeNs =
228 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
229 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
230
231 auto screenOffEvent =
232 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
233 processor->OnLogEvent(screenOffEvent.get());
234
235 auto screenOnEvent =
236 CreateScreenStateChangedEvent(configAddedTimeNs + 65, android::view::DISPLAY_STATE_ON);
237 processor->OnLogEvent(screenOnEvent.get());
238
239 screenOffEvent =
240 CreateScreenStateChangedEvent(configAddedTimeNs + 75, android::view::DISPLAY_STATE_OFF);
241 processor->OnLogEvent(screenOffEvent.get());
242
243 // Pulling alarm arrives on time and reset the sequential pulling alarm.
244 processor->informPullAlarmFired(expectedPullTimeNs + 1);
245 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
246
247 processor->informPullAlarmFired(expectedPullTimeNs + 1);
248
249 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 2 * bucketSizeNs + 15,
250 android::view::DISPLAY_STATE_ON);
251 processor->OnLogEvent(screenOnEvent.get());
252
253 processor->informPullAlarmFired(expectedPullTimeNs + 1);
254
255 processor->informPullAlarmFired(expectedPullTimeNs + 1);
256
257 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 4 * bucketSizeNs + 11,
258 android::view::DISPLAY_STATE_OFF);
259 processor->OnLogEvent(screenOffEvent.get());
260
261 processor->informPullAlarmFired(expectedPullTimeNs + 1);
262
263 processor->informPullAlarmFired(expectedPullTimeNs + 1);
264
265 ConfigMetricsReportList reports;
266 vector<uint8_t> buffer;
267 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
268 ADB_DUMP, FAST, &buffer);
269 EXPECT_TRUE(buffer.size() > 0);
270 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
271 backfillDimensionPath(&reports);
272 backfillStringInReport(&reports);
273 backfillStartEndTimestamp(&reports);
274 ASSERT_EQ(1, reports.reports_size());
275 ASSERT_EQ(1, reports.reports(0).metrics_size());
276 StatsLogReport::ValueMetricDataWrapper valueMetrics;
277 EXPECT_TRUE(reports.reports(0).metrics(0).has_estimated_data_bytes());
278 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
279 ASSERT_GT((int)valueMetrics.data_size(), 1);
280
281 auto data = valueMetrics.data(0);
282 EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
283 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
284 EXPECT_EQ(1 /* subsystem name field */,
285 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
286 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
287 // We have 4 buckets, the first one was incomplete since the condition was unknown.
288 ASSERT_EQ(4, data.bucket_info_size());
289
290 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
291 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
292 ASSERT_EQ(1, data.bucket_info(0).values_size());
293
294 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
295 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
296 ASSERT_EQ(1, data.bucket_info(1).values_size());
297
298 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
299 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
300 ASSERT_EQ(1, data.bucket_info(2).values_size());
301
302 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
303 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
304 ASSERT_EQ(1, data.bucket_info(3).values_size());
305
306 valueMetrics = reports.reports(0).metrics(0).value_metrics();
307 ASSERT_EQ(2, valueMetrics.skipped_size());
308
309 StatsLogReport::SkippedBuckets skipped = valueMetrics.skipped(0);
310 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, skipped.drop_event(0).drop_reason());
311 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 2 * bucketSizeNs)),
312 skipped.start_bucket_elapsed_nanos());
313 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 3 * bucketSizeNs)),
314 skipped.end_bucket_elapsed_nanos());
315
316 skipped = valueMetrics.skipped(1);
317 EXPECT_EQ(BucketDropReason::NO_DATA, skipped.drop_event(0).drop_reason());
318 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
319 skipped.start_bucket_elapsed_nanos());
320 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 6 * bucketSizeNs)),
321 skipped.end_bucket_elapsed_nanos());
322 }
323
TEST(ValueMetricE2eTest,TestPulledEvents_LateAlarm)324 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
325 auto config = CreateStatsdConfig();
326 int64_t baseTimeNs = getElapsedRealtimeNs();
327 // 10 mins == 2 bucket durations.
328 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
329 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
330
331 ConfigKey cfgKey;
332 auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
333 SharedRefBase::make<FakeSubsystemSleepCallback>(),
334 util::SUBSYSTEM_SLEEP_STATE);
335 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
336 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
337 processor->mPullerManager->ForceClearPullerCache();
338
339 int startBucketNum = processor->mMetricsManagers.begin()
340 ->second->mAllMetricProducers[0]
341 ->getCurrentBucketNum();
342 EXPECT_GT(startBucketNum, (int64_t)0);
343
344 // When creating the config, the value metric producer should register the alarm at the
345 // end of the current bucket.
346 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
347 EXPECT_EQ(bucketSizeNs,
348 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
349 int64_t& expectedPullTimeNs =
350 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
351 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
352
353 // Screen off/on/off events.
354 auto screenOffEvent =
355 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
356 processor->OnLogEvent(screenOffEvent.get());
357
358 auto screenOnEvent =
359 CreateScreenStateChangedEvent(configAddedTimeNs + 65, android::view::DISPLAY_STATE_ON);
360 processor->OnLogEvent(screenOnEvent.get());
361
362 screenOffEvent =
363 CreateScreenStateChangedEvent(configAddedTimeNs + 75, android::view::DISPLAY_STATE_OFF);
364 processor->OnLogEvent(screenOffEvent.get());
365
366 // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
367 // future, data will be skipped.
368 processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
369 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
370
371 // This screen state change will start a new bucket.
372 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 4 * bucketSizeNs + 65,
373 android::view::DISPLAY_STATE_ON);
374 processor->OnLogEvent(screenOnEvent.get());
375
376 // The alarm is delayed but we already created a bucket thanks to the screen state condition.
377 // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
378 processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
379 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
380
381 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 6 * bucketSizeNs + 31,
382 android::view::DISPLAY_STATE_OFF);
383 processor->OnLogEvent(screenOffEvent.get());
384
385 processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
386 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
387
388 processor->informPullAlarmFired(expectedPullTimeNs + 1);
389 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
390
391 ConfigMetricsReportList reports;
392 vector<uint8_t> buffer;
393 processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
394 ADB_DUMP, FAST, &buffer);
395 EXPECT_TRUE(buffer.size() > 0);
396 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
397 backfillDimensionPath(&reports);
398 backfillStringInReport(&reports);
399 backfillStartEndTimestamp(&reports);
400 ASSERT_EQ(1, reports.reports_size());
401 ASSERT_EQ(1, reports.reports(0).metrics_size());
402 StatsLogReport::ValueMetricDataWrapper valueMetrics;
403 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
404 ASSERT_GT((int)valueMetrics.data_size(), 1);
405
406 auto data = valueMetrics.data(0);
407 EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
408 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
409 EXPECT_EQ(1 /* subsystem name field */,
410 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
411 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
412 ASSERT_EQ(3, data.bucket_info_size());
413
414 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
415 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
416 ASSERT_EQ(1, data.bucket_info(0).values_size());
417
418 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
419 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
420 ASSERT_EQ(1, data.bucket_info(1).values_size());
421
422 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
423 EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
424 ASSERT_EQ(1, data.bucket_info(2).values_size());
425
426 valueMetrics = reports.reports(0).metrics(0).value_metrics();
427 ASSERT_EQ(3, valueMetrics.skipped_size());
428
429 StatsLogReport::SkippedBuckets skipped = valueMetrics.skipped(0);
430 EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, skipped.drop_event(0).drop_reason());
431 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 2 * bucketSizeNs)),
432 skipped.start_bucket_elapsed_nanos());
433 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
434 skipped.end_bucket_elapsed_nanos());
435
436 skipped = valueMetrics.skipped(1);
437 EXPECT_EQ(BucketDropReason::NO_DATA, skipped.drop_event(0).drop_reason());
438 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 6 * bucketSizeNs)),
439 skipped.start_bucket_elapsed_nanos());
440 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 7 * bucketSizeNs)),
441 skipped.end_bucket_elapsed_nanos());
442
443 skipped = valueMetrics.skipped(2);
444 EXPECT_EQ(BucketDropReason::NO_DATA, skipped.drop_event(0).drop_reason());
445 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 7 * bucketSizeNs)),
446 skipped.start_bucket_elapsed_nanos());
447 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 8 * bucketSizeNs)),
448 skipped.end_bucket_elapsed_nanos());
449 }
450
TEST(ValueMetricE2eTest,TestPulledEvents_WithActivation)451 TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
452 auto config = CreateStatsdConfig(false);
453 int64_t baseTimeNs = getElapsedRealtimeNs();
454 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
455 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
456
457 auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
458 *config.add_atom_matcher() = batterySaverStartMatcher;
459 const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
460 auto metric_activation = config.add_metric_activation();
461 metric_activation->set_metric_id(metricId);
462 metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
463 auto event_activation = metric_activation->add_event_activation();
464 event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
465 event_activation->set_ttl_seconds(ttlNs / 1000000000);
466
467 StatsdStats::getInstance().reset();
468
469 ConfigKey cfgKey;
470 auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
471 SharedRefBase::make<FakeSubsystemSleepCallback>(),
472 util::SUBSYSTEM_SLEEP_STATE);
473 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
474 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
475 processor->mPullerManager->ForceClearPullerCache();
476
477 const int startBucketNum = processor->mMetricsManagers.begin()
478 ->second->mAllMetricProducers[0]
479 ->getCurrentBucketNum();
480 EXPECT_EQ(startBucketNum, 2);
481 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
482
483 // When creating the config, the value metric producer should register the alarm at the
484 // end of the current bucket.
485 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
486 EXPECT_EQ(bucketSizeNs,
487 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
488 int64_t& expectedPullTimeNs =
489 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
490 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
491
492 // Initialize metric.
493 const int64_t metricInitTimeNs = configAddedTimeNs + 1; // 10 mins + 1 ns.
494 processor->onStatsdInitCompleted(metricInitTimeNs);
495
496 // Check no pull occurred since metric not active.
497 StatsdStatsReport_PulledAtomStats pulledAtomStats =
498 getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
499 EXPECT_EQ(pulledAtomStats.atom_id(), util::SUBSYSTEM_SLEEP_STATE);
500 EXPECT_EQ(pulledAtomStats.total_pull(), 0);
501
502 // Check skip bucket is not added when metric is not active.
503 int64_t dumpReportTimeNs = metricInitTimeNs + 1; // 10 mins + 2 ns.
504 vector<uint8_t> buffer;
505 processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
506 true /* erase_data */, ADB_DUMP, FAST, &buffer);
507 ConfigMetricsReportList reports;
508 EXPECT_TRUE(buffer.size() > 0);
509 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
510 ASSERT_EQ(1, reports.reports_size());
511 ASSERT_EQ(1, reports.reports(0).metrics_size());
512 StatsLogReport::ValueMetricDataWrapper valueMetrics =
513 reports.reports(0).metrics(0).value_metrics();
514 EXPECT_EQ(valueMetrics.skipped_size(), 0);
515
516 // App upgrade.
517 const int64_t appUpgradeTimeNs = dumpReportTimeNs + 1; // 10 mins + 3 ns.
518 processor->notifyAppUpgrade(appUpgradeTimeNs, "appName", 1000 /* uid */, 2 /* version */);
519
520 // Check no pull occurred since metric not active.
521 pulledAtomStats = getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
522 EXPECT_EQ(pulledAtomStats.atom_id(), util::SUBSYSTEM_SLEEP_STATE);
523 EXPECT_EQ(pulledAtomStats.total_pull(), 0);
524
525 // Check skip bucket is not added when metric is not active.
526 dumpReportTimeNs = appUpgradeTimeNs + 1; // 10 mins + 4 ns.
527 buffer.clear();
528 processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
529 true /* erase_data */, ADB_DUMP, FAST, &buffer);
530 EXPECT_TRUE(buffer.size() > 0);
531 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
532 ASSERT_EQ(1, reports.reports_size());
533 ASSERT_EQ(1, reports.reports(0).metrics_size());
534 valueMetrics = reports.reports(0).metrics(0).value_metrics();
535 EXPECT_EQ(valueMetrics.skipped_size(), 0);
536
537 // Dump report with a pull. The pull should not happen because metric is inactive.
538 dumpReportTimeNs = dumpReportTimeNs + 1; // 10 mins + 6 ns.
539 buffer.clear();
540 processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
541 true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
542 pulledAtomStats = getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
543 EXPECT_EQ(pulledAtomStats.atom_id(), util::SUBSYSTEM_SLEEP_STATE);
544 EXPECT_EQ(pulledAtomStats.total_pull(), 0);
545
546 // Check skipped bucket is not added from the dump operation when metric is not active.
547 EXPECT_TRUE(buffer.size() > 0);
548 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
549 ASSERT_EQ(1, reports.reports_size());
550 ASSERT_EQ(1, reports.reports(0).metrics_size());
551 valueMetrics = reports.reports(0).metrics(0).value_metrics();
552 EXPECT_EQ(valueMetrics.skipped_size(), 0);
553
554 // Pulling alarm arrives on time and reset the sequential pulling alarm. This bucket is skipped.
555 processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
556 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
557 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
558
559 // Activate the metric. A pull occurs here that sets the base.
560 // 15 mins + 2 ms
561 const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
562 auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
563 processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
564 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
565
566 // This bucket should be kept. 1 total
567 processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
568 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
569
570 // 25 mins + 2 ns.
571 // This bucket should be kept. 2 total
572 processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
573 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
574
575 // Create random event to deactivate metric.
576 // A pull occurs here and a partial bucket is created. The bucket ending here is kept. 3 total.
577 // 25 mins + 2 ms + 1 ns.
578 const int64_t deactivationNs = activationNs + ttlNs + 1;
579 auto deactivationEvent = CreateScreenBrightnessChangedEvent(deactivationNs, 50);
580 processor->OnLogEvent(deactivationEvent.get());
581 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
582
583 // 30 mins + 3 ns. This bucket is skipped.
584 processor->informPullAlarmFired(expectedPullTimeNs + 3);
585 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
586
587 // 35 mins + 4 ns. This bucket is skipped
588 processor->informPullAlarmFired(expectedPullTimeNs + 4);
589 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
590
591 dumpReportTimeNs = configAddedTimeNs + 6 * bucketSizeNs + 10;
592 buffer.clear();
593 // 40 mins + 10 ns.
594 processor->onDumpReport(cfgKey, dumpReportTimeNs, false /* include_current_partial_bucket */,
595 true /* erase_data */, ADB_DUMP, FAST, &buffer);
596 EXPECT_TRUE(buffer.size() > 0);
597 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
598 backfillDimensionPath(&reports);
599 backfillStringInReport(&reports);
600 backfillStartEndTimestamp(&reports);
601 ASSERT_EQ(1, reports.reports_size());
602 ASSERT_EQ(1, reports.reports(0).metrics_size());
603 valueMetrics = StatsLogReport::ValueMetricDataWrapper();
604 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
605 ASSERT_GT((int)valueMetrics.data_size(), 0);
606
607 auto data = valueMetrics.data(0);
608 EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
609 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
610 EXPECT_EQ(1 /* subsystem name field */,
611 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
612 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
613 // We have 3 full buckets, the two surrounding the activation are dropped.
614 ASSERT_EQ(3, data.bucket_info_size());
615
616 auto bucketInfo = data.bucket_info(0);
617 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
618 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
619 ASSERT_EQ(1, bucketInfo.values_size());
620
621 bucketInfo = data.bucket_info(1);
622 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
623 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
624 ASSERT_EQ(1, bucketInfo.values_size());
625
626 bucketInfo = data.bucket_info(2);
627 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
628 bucketInfo.start_bucket_elapsed_nanos());
629 EXPECT_EQ(MillisToNano(NanoToMillis(deactivationNs)), bucketInfo.end_bucket_elapsed_nanos());
630 ASSERT_EQ(1, bucketInfo.values_size());
631
632 // Check skipped bucket is not added after deactivation.
633 dumpReportTimeNs = configAddedTimeNs + 7 * bucketSizeNs + 10;
634 buffer.clear();
635 // 45 mins + 10 ns.
636 processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
637 true /* erase_data */, ADB_DUMP, FAST, &buffer);
638 EXPECT_TRUE(buffer.size() > 0);
639 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
640 ASSERT_EQ(1, reports.reports_size());
641 ASSERT_EQ(1, reports.reports(0).metrics_size());
642 valueMetrics = reports.reports(0).metrics(0).value_metrics();
643 EXPECT_EQ(valueMetrics.skipped_size(), 0);
644 }
645
646 /**
647 * Test initialization of a simple value metric that is sliced by a state.
648 *
649 * ValueCpuUserTimePerScreenState
650 */
TEST(ValueMetricE2eTest,TestInitWithSlicedState)651 TEST(ValueMetricE2eTest, TestInitWithSlicedState) {
652 // Create config.
653 StatsdConfig config;
654
655 auto pulledAtomMatcher =
656 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
657 *config.add_atom_matcher() = pulledAtomMatcher;
658
659 auto screenState = CreateScreenState();
660 *config.add_state() = screenState;
661
662 // Create value metric that slices by screen state without a map.
663 int64_t metricId = 123456;
664 auto valueMetric = config.add_value_metric();
665 valueMetric->set_id(metricId);
666 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
667 valueMetric->set_what(pulledAtomMatcher.id());
668 *valueMetric->mutable_value_field() =
669 CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
670 valueMetric->add_slice_by_state(screenState.id());
671 valueMetric->set_max_pull_delay_sec(INT_MAX);
672
673 // Initialize StatsLogProcessor.
674 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
675 const uint64_t bucketSizeNs =
676 TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000LL;
677 int uid = 12345;
678 int64_t cfgId = 98765;
679 ConfigKey cfgKey(uid, cfgId);
680
681 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
682
683 // Check that StateTrackers were initialized correctly.
684 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
685 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
686
687 // Check that NumericValueMetricProducer was initialized correctly.
688 ASSERT_EQ(1U, processor->mMetricsManagers.size());
689 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
690 EXPECT_TRUE(metricsManager->isConfigValid());
691 ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
692 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
693 ASSERT_EQ(1, metricProducer->mSlicedStateAtoms.size());
694 EXPECT_EQ(SCREEN_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
695 ASSERT_EQ(0, metricProducer->mStateGroupMap.size());
696 }
697
698 /**
699 * Test initialization of a value metric that is sliced by state and has
700 * dimensions_in_what.
701 *
702 * ValueCpuUserTimePerUidPerUidProcessState
703 */
TEST(ValueMetricE2eTest,TestInitWithSlicedState_WithDimensions)704 TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions) {
705 // Create config.
706 StatsdConfig config;
707
708 auto cpuTimePerUidMatcher =
709 CreateSimpleAtomMatcher("CpuTimePerUidMatcher", util::CPU_TIME_PER_UID);
710 *config.add_atom_matcher() = cpuTimePerUidMatcher;
711
712 auto uidProcessState = CreateUidProcessState();
713 *config.add_state() = uidProcessState;
714
715 // Create value metric that slices by screen state with a complete map.
716 int64_t metricId = 123456;
717 auto valueMetric = config.add_value_metric();
718 valueMetric->set_id(metricId);
719 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
720 valueMetric->set_what(cpuTimePerUidMatcher.id());
721 *valueMetric->mutable_value_field() =
722 CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
723 *valueMetric->mutable_dimensions_in_what() =
724 CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
725 valueMetric->add_slice_by_state(uidProcessState.id());
726 MetricStateLink* stateLink = valueMetric->add_state_link();
727 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
728 auto fieldsInWhat = stateLink->mutable_fields_in_what();
729 *fieldsInWhat = CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
730 auto fieldsInState = stateLink->mutable_fields_in_state();
731 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
732 valueMetric->set_max_pull_delay_sec(INT_MAX);
733
734 // Initialize StatsLogProcessor.
735 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
736 int uid = 12345;
737 int64_t cfgId = 98765;
738 ConfigKey cfgKey(uid, cfgId);
739
740 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
741
742 // Check that StateTrackers were initialized correctly.
743 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
744 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
745
746 // Check that NumericValueMetricProducer was initialized correctly.
747 ASSERT_EQ(1U, processor->mMetricsManagers.size());
748 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
749 EXPECT_TRUE(metricsManager->isConfigValid());
750 ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
751 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
752 ASSERT_EQ(1, metricProducer->mSlicedStateAtoms.size());
753 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
754 ASSERT_EQ(0, metricProducer->mStateGroupMap.size());
755 }
756
757 /**
758 * Test initialization of a value metric that is sliced by state and has
759 * dimensions_in_what.
760 *
761 * ValueCpuUserTimePerUidPerUidProcessState
762 */
TEST(ValueMetricE2eTest,TestInitWithSlicedState_WithIncorrectDimensions)763 TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions) {
764 // Create config.
765 StatsdConfig config;
766
767 auto cpuTimePerUidMatcher =
768 CreateSimpleAtomMatcher("CpuTimePerUidMatcher", util::CPU_TIME_PER_UID);
769 *config.add_atom_matcher() = cpuTimePerUidMatcher;
770
771 auto uidProcessState = CreateUidProcessState();
772 *config.add_state() = uidProcessState;
773
774 // Create value metric that slices by screen state with a complete map.
775 int64_t metricId = 123456;
776 auto valueMetric = config.add_value_metric();
777 valueMetric->set_id(metricId);
778 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
779 valueMetric->set_what(cpuTimePerUidMatcher.id());
780 *valueMetric->mutable_value_field() =
781 CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
782 valueMetric->add_slice_by_state(uidProcessState.id());
783 MetricStateLink* stateLink = valueMetric->add_state_link();
784 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
785 auto fieldsInWhat = stateLink->mutable_fields_in_what();
786 *fieldsInWhat = CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
787 auto fieldsInState = stateLink->mutable_fields_in_state();
788 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
789 valueMetric->set_max_pull_delay_sec(INT_MAX);
790
791 // Initialize StatsLogProcessor.
792 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
793 int uid = 12345;
794 int64_t cfgId = 98765;
795 ConfigKey cfgKey(uid, cfgId);
796 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
797
798 // No StateTrackers are initialized.
799 EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
800
801 // Config initialization fails.
802 ASSERT_EQ(0, processor->mMetricsManagers.size());
803 }
804
TEST(ValueMetricE2eTest,TestInitWithValueFieldPositionALL)805 TEST(ValueMetricE2eTest, TestInitWithValueFieldPositionALL) {
806 // Create config.
807 StatsdConfig config;
808
809 AtomMatcher testAtomReportedMatcher =
810 CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
811 *config.add_atom_matcher() = testAtomReportedMatcher;
812
813 // Create value metric.
814 int64_t metricId = 123456;
815 ValueMetric* valueMetric = config.add_value_metric();
816 valueMetric->set_id(metricId);
817 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
818 valueMetric->set_what(testAtomReportedMatcher.id());
819 *valueMetric->mutable_value_field() = CreateRepeatedDimensions(
820 util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/}, {Position::ALL});
821
822 // Initialize StatsLogProcessor.
823 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
824 int uid = 12345;
825 int64_t cfgId = 98765;
826 ConfigKey cfgKey(uid, cfgId);
827 sp<StatsLogProcessor> processor =
828 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
829
830 // Config initialization fails.
831 ASSERT_EQ(0, processor->mMetricsManagers.size());
832 }
833
TEST(ValueMetricE2eTest,TestInitWithMultipleAggTypes)834 TEST(ValueMetricE2eTest, TestInitWithMultipleAggTypes) {
835 // Create config.
836 StatsdConfig config;
837
838 AtomMatcher testAtomReportedMatcher =
839 CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
840 *config.add_atom_matcher() = testAtomReportedMatcher;
841
842 // Create value metric.
843 int64_t metricId = 123456;
844 ValueMetric* valueMetric = config.add_value_metric();
845 valueMetric->set_id(metricId);
846 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
847 valueMetric->set_what(testAtomReportedMatcher.id());
848 *valueMetric->mutable_value_field() = CreateDimensions(
849 util::TEST_ATOM_REPORTED, {2 /*int_field*/, 2 /*int_field*/, 3 /*long_field*/,
850 3 /*long_field*/, 3 /*long_field*/});
851 valueMetric->add_aggregation_types(ValueMetric::SUM);
852 valueMetric->add_aggregation_types(ValueMetric::MIN);
853 valueMetric->add_aggregation_types(ValueMetric::MAX);
854 valueMetric->add_aggregation_types(ValueMetric::AVG);
855 valueMetric->add_aggregation_types(ValueMetric::MIN);
856
857 // Initialize StatsLogProcessor.
858 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
859 int uid = 12345;
860 int64_t cfgId = 98765;
861 ConfigKey cfgKey(uid, cfgId);
862 sp<StatsLogProcessor> processor =
863 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
864
865 ASSERT_EQ(1, processor->mMetricsManagers.size());
866 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
867 EXPECT_TRUE(metricsManager->isConfigValid());
868 ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
869 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
870 NumericValueMetricProducer* valueProducer =
871 static_cast<NumericValueMetricProducer*>(metricProducer.get());
872 ASSERT_EQ(5u, valueProducer->mAggregationTypes.size());
873 EXPECT_EQ(ValueMetric::SUM, valueProducer->mAggregationTypes[0]);
874 EXPECT_EQ(ValueMetric::MIN, valueProducer->mAggregationTypes[1]);
875 EXPECT_EQ(ValueMetric::MAX, valueProducer->mAggregationTypes[2]);
876 EXPECT_EQ(ValueMetric::AVG, valueProducer->mAggregationTypes[3]);
877 EXPECT_EQ(ValueMetric::MIN, valueProducer->mAggregationTypes[4]);
878 EXPECT_TRUE(valueProducer->mIncludeSampleSize);
879 }
880
TEST(ValueMetricE2eTest,TestInitWithDefaultAggType)881 TEST(ValueMetricE2eTest, TestInitWithDefaultAggType) {
882 // Create config.
883 StatsdConfig config;
884
885 AtomMatcher testAtomReportedMatcher =
886 CreateSimpleAtomMatcher("TestAtomReportedMatcher", util::TEST_ATOM_REPORTED);
887 *config.add_atom_matcher() = testAtomReportedMatcher;
888
889 // Create value metric.
890 int64_t metricId = 123456;
891 ValueMetric* valueMetric = config.add_value_metric();
892 valueMetric->set_id(metricId);
893 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
894 valueMetric->set_what(testAtomReportedMatcher.id());
895 *valueMetric->mutable_value_field() =
896 CreateDimensions(util::TEST_ATOM_REPORTED, {3 /*long_field*/, 2 /*int_field*/});
897
898 // Initialize StatsLogProcessor.
899 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
900 int uid = 12345;
901 int64_t cfgId = 98765;
902 ConfigKey cfgKey(uid, cfgId);
903 sp<StatsLogProcessor> processor =
904 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
905
906 ASSERT_EQ(1, processor->mMetricsManagers.size());
907 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
908 EXPECT_TRUE(metricsManager->isConfigValid());
909 ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
910 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
911 NumericValueMetricProducer* valueProducer =
912 static_cast<NumericValueMetricProducer*>(metricProducer.get());
913 ASSERT_EQ(1u, valueProducer->mAggregationTypes.size());
914 EXPECT_EQ(ValueMetric::SUM, valueProducer->mAggregationTypes[0]);
915 EXPECT_FALSE(valueProducer->mIncludeSampleSize);
916 }
917
918 #else
919 GTEST_LOG_(INFO) << "This test does nothing.\n";
920 #endif
921
922 } // namespace statsd
923 } // namespace os
924 } // namespace android
925