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 "src/StatsLogProcessor.h"
19 #include "src/stats_log_util.h"
20 #include "tests/statsd_test_util.h"
21
22 #include <vector>
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_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
39 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
40 auto pulledAtomMatcher =
41 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
42 *config.add_atom_matcher() = pulledAtomMatcher;
43 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
44 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
45
46 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
47 *config.add_predicate() = screenIsOffPredicate;
48
49 auto valueMetric = config.add_value_metric();
50 valueMetric->set_id(metricId);
51 valueMetric->set_what(pulledAtomMatcher.id());
52 if (useCondition) {
53 valueMetric->set_condition(screenIsOffPredicate.id());
54 }
55 *valueMetric->mutable_value_field() =
56 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
57 *valueMetric->mutable_dimensions_in_what() =
58 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
59 valueMetric->set_bucket(FIVE_MINUTES);
60 valueMetric->set_use_absolute_value_on_reset(true);
61 valueMetric->set_skip_zero_diff_output(false);
62 valueMetric->set_max_pull_delay_sec(INT_MAX);
63 return config;
64 }
65
CreateStatsdConfigWithStates()66 StatsdConfig CreateStatsdConfigWithStates() {
67 StatsdConfig config;
68 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
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 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
278 ASSERT_GT((int)valueMetrics.data_size(), 1);
279
280 auto data = valueMetrics.data(0);
281 EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
282 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
283 EXPECT_EQ(1 /* subsystem name field */,
284 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
285 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
286 // We have 4 buckets, the first one was incomplete since the condition was unknown.
287 ASSERT_EQ(4, data.bucket_info_size());
288
289 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
290 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
291 ASSERT_EQ(1, data.bucket_info(0).values_size());
292
293 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
294 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
295 ASSERT_EQ(1, data.bucket_info(1).values_size());
296
297 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
298 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
299 ASSERT_EQ(1, data.bucket_info(2).values_size());
300
301 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
302 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
303 ASSERT_EQ(1, data.bucket_info(3).values_size());
304 }
305
TEST(ValueMetricE2eTest,TestPulledEvents_LateAlarm)306 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
307 auto config = CreateStatsdConfig();
308 int64_t baseTimeNs = getElapsedRealtimeNs();
309 // 10 mins == 2 bucket durations.
310 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
311 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
312
313 ConfigKey cfgKey;
314 auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
315 SharedRefBase::make<FakeSubsystemSleepCallback>(),
316 util::SUBSYSTEM_SLEEP_STATE);
317 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
318 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
319 processor->mPullerManager->ForceClearPullerCache();
320
321 int startBucketNum = processor->mMetricsManagers.begin()
322 ->second->mAllMetricProducers[0]
323 ->getCurrentBucketNum();
324 EXPECT_GT(startBucketNum, (int64_t)0);
325
326 // When creating the config, the value metric producer should register the alarm at the
327 // end of the current bucket.
328 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
329 EXPECT_EQ(bucketSizeNs,
330 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
331 int64_t& expectedPullTimeNs =
332 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
333 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
334
335 // Screen off/on/off events.
336 auto screenOffEvent =
337 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
338 processor->OnLogEvent(screenOffEvent.get());
339
340 auto screenOnEvent =
341 CreateScreenStateChangedEvent(configAddedTimeNs + 65, android::view::DISPLAY_STATE_ON);
342 processor->OnLogEvent(screenOnEvent.get());
343
344 screenOffEvent =
345 CreateScreenStateChangedEvent(configAddedTimeNs + 75, android::view::DISPLAY_STATE_OFF);
346 processor->OnLogEvent(screenOffEvent.get());
347
348 // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
349 // future, data will be skipped.
350 processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
351 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
352
353 // This screen state change will start a new bucket.
354 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 4 * bucketSizeNs + 65,
355 android::view::DISPLAY_STATE_ON);
356 processor->OnLogEvent(screenOnEvent.get());
357
358 // The alarm is delayed but we already created a bucket thanks to the screen state condition.
359 // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
360 processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
361 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
362
363 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 6 * bucketSizeNs + 31,
364 android::view::DISPLAY_STATE_OFF);
365 processor->OnLogEvent(screenOffEvent.get());
366
367 processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
368 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
369
370 processor->informPullAlarmFired(expectedPullTimeNs + 1);
371 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
372
373 ConfigMetricsReportList reports;
374 vector<uint8_t> buffer;
375 processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
376 ADB_DUMP, FAST, &buffer);
377 EXPECT_TRUE(buffer.size() > 0);
378 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
379 backfillDimensionPath(&reports);
380 backfillStringInReport(&reports);
381 backfillStartEndTimestamp(&reports);
382 ASSERT_EQ(1, reports.reports_size());
383 ASSERT_EQ(1, reports.reports(0).metrics_size());
384 StatsLogReport::ValueMetricDataWrapper valueMetrics;
385 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
386 ASSERT_GT((int)valueMetrics.data_size(), 1);
387
388 auto data = valueMetrics.data(0);
389 EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
390 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
391 EXPECT_EQ(1 /* subsystem name field */,
392 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
393 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
394 ASSERT_EQ(3, data.bucket_info_size());
395
396 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
397 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
398 ASSERT_EQ(1, data.bucket_info(0).values_size());
399
400 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
401 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
402 ASSERT_EQ(1, data.bucket_info(1).values_size());
403
404 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
405 EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
406 ASSERT_EQ(1, data.bucket_info(2).values_size());
407 }
408
TEST(ValueMetricE2eTest,TestPulledEvents_WithActivation)409 TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
410 auto config = CreateStatsdConfig(false);
411 int64_t baseTimeNs = getElapsedRealtimeNs();
412 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
413 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
414
415 auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
416 *config.add_atom_matcher() = batterySaverStartMatcher;
417 const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
418 auto metric_activation = config.add_metric_activation();
419 metric_activation->set_metric_id(metricId);
420 metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
421 auto event_activation = metric_activation->add_event_activation();
422 event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
423 event_activation->set_ttl_seconds(ttlNs / 1000000000);
424
425 ConfigKey cfgKey;
426 auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
427 SharedRefBase::make<FakeSubsystemSleepCallback>(),
428 util::SUBSYSTEM_SLEEP_STATE);
429 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
430 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
431 processor->mPullerManager->ForceClearPullerCache();
432
433 int startBucketNum = processor->mMetricsManagers.begin()
434 ->second->mAllMetricProducers[0]
435 ->getCurrentBucketNum();
436 EXPECT_GT(startBucketNum, (int64_t)0);
437 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
438
439 // When creating the config, the value metric producer should register the alarm at the
440 // end of the current bucket.
441 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
442 EXPECT_EQ(bucketSizeNs,
443 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
444 int64_t& expectedPullTimeNs =
445 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
446 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
447
448 // Pulling alarm arrives on time and reset the sequential pulling alarm.
449 processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
450 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
451 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
452
453 // Activate the metric. A pull occurs here
454 const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
455 auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
456 processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
457 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
458
459 processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
460 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
461
462 processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
463 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
464
465 // Create random event to deactivate metric.
466 auto deactivationEvent = CreateScreenBrightnessChangedEvent(activationNs + ttlNs + 1, 50);
467 processor->OnLogEvent(deactivationEvent.get());
468 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
469
470 processor->informPullAlarmFired(expectedPullTimeNs + 3);
471 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
472
473 processor->informPullAlarmFired(expectedPullTimeNs + 4);
474 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
475
476 ConfigMetricsReportList reports;
477 vector<uint8_t> buffer;
478 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
479 ADB_DUMP, FAST, &buffer);
480 EXPECT_TRUE(buffer.size() > 0);
481 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
482 backfillDimensionPath(&reports);
483 backfillStringInReport(&reports);
484 backfillStartEndTimestamp(&reports);
485 ASSERT_EQ(1, reports.reports_size());
486 ASSERT_EQ(1, reports.reports(0).metrics_size());
487 StatsLogReport::ValueMetricDataWrapper valueMetrics;
488 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
489 ASSERT_GT((int)valueMetrics.data_size(), 0);
490
491 auto data = valueMetrics.data(0);
492 EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
493 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
494 EXPECT_EQ(1 /* subsystem name field */,
495 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
496 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
497 // We have 2 full buckets, the two surrounding the activation are dropped.
498 ASSERT_EQ(2, data.bucket_info_size());
499
500 auto bucketInfo = data.bucket_info(0);
501 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
502 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
503 ASSERT_EQ(1, bucketInfo.values_size());
504
505 bucketInfo = data.bucket_info(1);
506 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
507 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
508 ASSERT_EQ(1, bucketInfo.values_size());
509 }
510
511 /**
512 * Test initialization of a simple value metric that is sliced by a state.
513 *
514 * ValueCpuUserTimePerScreenState
515 */
TEST(ValueMetricE2eTest,TestInitWithSlicedState)516 TEST(ValueMetricE2eTest, TestInitWithSlicedState) {
517 // Create config.
518 StatsdConfig config;
519 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
520
521 auto pulledAtomMatcher =
522 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
523 *config.add_atom_matcher() = pulledAtomMatcher;
524
525 auto screenState = CreateScreenState();
526 *config.add_state() = screenState;
527
528 // Create value metric that slices by screen state without a map.
529 int64_t metricId = 123456;
530 auto valueMetric = config.add_value_metric();
531 valueMetric->set_id(metricId);
532 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
533 valueMetric->set_what(pulledAtomMatcher.id());
534 *valueMetric->mutable_value_field() =
535 CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
536 valueMetric->add_slice_by_state(screenState.id());
537 valueMetric->set_max_pull_delay_sec(INT_MAX);
538
539 // Initialize StatsLogProcessor.
540 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
541 const uint64_t bucketSizeNs =
542 TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000LL;
543 int uid = 12345;
544 int64_t cfgId = 98765;
545 ConfigKey cfgKey(uid, cfgId);
546
547 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
548
549 // Check that StateTrackers were initialized correctly.
550 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
551 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
552
553 // Check that ValueMetricProducer was initialized correctly.
554 ASSERT_EQ(1U, processor->mMetricsManagers.size());
555 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
556 EXPECT_TRUE(metricsManager->isConfigValid());
557 ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
558 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
559 ASSERT_EQ(1, metricProducer->mSlicedStateAtoms.size());
560 EXPECT_EQ(SCREEN_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
561 ASSERT_EQ(0, metricProducer->mStateGroupMap.size());
562 }
563
564 /**
565 * Test initialization of a value metric that is sliced by state and has
566 * dimensions_in_what.
567 *
568 * ValueCpuUserTimePerUidPerUidProcessState
569 */
TEST(ValueMetricE2eTest,TestInitWithSlicedState_WithDimensions)570 TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions) {
571 // Create config.
572 StatsdConfig config;
573 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
574
575 auto cpuTimePerUidMatcher =
576 CreateSimpleAtomMatcher("CpuTimePerUidMatcher", util::CPU_TIME_PER_UID);
577 *config.add_atom_matcher() = cpuTimePerUidMatcher;
578
579 auto uidProcessState = CreateUidProcessState();
580 *config.add_state() = uidProcessState;
581
582 // Create value metric that slices by screen state with a complete map.
583 int64_t metricId = 123456;
584 auto valueMetric = config.add_value_metric();
585 valueMetric->set_id(metricId);
586 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
587 valueMetric->set_what(cpuTimePerUidMatcher.id());
588 *valueMetric->mutable_value_field() =
589 CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
590 *valueMetric->mutable_dimensions_in_what() =
591 CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
592 valueMetric->add_slice_by_state(uidProcessState.id());
593 MetricStateLink* stateLink = valueMetric->add_state_link();
594 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
595 auto fieldsInWhat = stateLink->mutable_fields_in_what();
596 *fieldsInWhat = CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
597 auto fieldsInState = stateLink->mutable_fields_in_state();
598 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
599 valueMetric->set_max_pull_delay_sec(INT_MAX);
600
601 // Initialize StatsLogProcessor.
602 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
603 int uid = 12345;
604 int64_t cfgId = 98765;
605 ConfigKey cfgKey(uid, cfgId);
606
607 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
608
609 // Check that StateTrackers were initialized correctly.
610 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
611 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
612
613 // Check that ValueMetricProducer was initialized correctly.
614 ASSERT_EQ(1U, processor->mMetricsManagers.size());
615 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
616 EXPECT_TRUE(metricsManager->isConfigValid());
617 ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
618 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
619 ASSERT_EQ(1, metricProducer->mSlicedStateAtoms.size());
620 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
621 ASSERT_EQ(0, metricProducer->mStateGroupMap.size());
622 }
623
624 /**
625 * Test initialization of a value metric that is sliced by state and has
626 * dimensions_in_what.
627 *
628 * ValueCpuUserTimePerUidPerUidProcessState
629 */
TEST(ValueMetricE2eTest,TestInitWithSlicedState_WithIncorrectDimensions)630 TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions) {
631 // Create config.
632 StatsdConfig config;
633 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
634
635 auto cpuTimePerUidMatcher =
636 CreateSimpleAtomMatcher("CpuTimePerUidMatcher", util::CPU_TIME_PER_UID);
637 *config.add_atom_matcher() = cpuTimePerUidMatcher;
638
639 auto uidProcessState = CreateUidProcessState();
640 *config.add_state() = uidProcessState;
641
642 // Create value metric that slices by screen state with a complete map.
643 int64_t metricId = 123456;
644 auto valueMetric = config.add_value_metric();
645 valueMetric->set_id(metricId);
646 valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
647 valueMetric->set_what(cpuTimePerUidMatcher.id());
648 *valueMetric->mutable_value_field() =
649 CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
650 valueMetric->add_slice_by_state(uidProcessState.id());
651 MetricStateLink* stateLink = valueMetric->add_state_link();
652 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
653 auto fieldsInWhat = stateLink->mutable_fields_in_what();
654 *fieldsInWhat = CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
655 auto fieldsInState = stateLink->mutable_fields_in_state();
656 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
657 valueMetric->set_max_pull_delay_sec(INT_MAX);
658
659 // Initialize StatsLogProcessor.
660 const uint64_t bucketStartTimeNs = 10000000000; // 0:10
661 int uid = 12345;
662 int64_t cfgId = 98765;
663 ConfigKey cfgKey(uid, cfgId);
664 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
665
666 // No StateTrackers are initialized.
667 EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
668
669 // Config initialization fails.
670 ASSERT_EQ(0, processor->mMetricsManagers.size());
671 }
672
673 #else
674 GTEST_LOG_(INFO) << "This test does nothing.\n";
675 #endif
676
677 } // namespace statsd
678 } // namespace os
679 } // namespace android
680