1 // Copyright (C) 2020 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-base/properties.h>
16 #include <android-base/stringprintf.h>
17 #include <android/binder_interface_utils.h>
18 #include <gtest/gtest.h>
19 
20 #include "flags/FlagProvider.h"
21 #include "src/StatsLogProcessor.h"
22 #include "src/storage/StorageManager.h"
23 #include "tests/statsd_test_util.h"
24 
25 namespace android {
26 namespace os {
27 namespace statsd {
28 
29 #ifdef __ANDROID__
30 #define STATS_DATA_DIR "/data/misc/stats-data"
31 
32 using android::base::SetProperty;
33 using android::base::StringPrintf;
34 using ::ndk::SharedRefBase;
35 using namespace std;
36 
37 namespace {
38 
CreateSimpleConfig()39 StatsdConfig CreateSimpleConfig() {
40     StatsdConfig config;
41     config.add_allowed_log_source("AID_STATSD");
42     config.set_hash_strings_in_metric_report(false);
43 
44     *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
45     // Simple count metric so the config isn't empty.
46     CountMetric* countMetric1 = config.add_count_metric();
47     countMetric1->set_id(StringToId("Count1"));
48     countMetric1->set_what(config.atom_matcher(0).id());
49     countMetric1->set_bucket(FIVE_MINUTES);
50     return config;
51 }
52 }  // namespace
53 
54 // Setup for parameterized tests.
55 class ConfigUpdateE2eAbTest : public TestWithParam<bool> {
56 };
57 
58 INSTANTIATE_TEST_SUITE_P(ConfigUpdateE2eAbTest, ConfigUpdateE2eAbTest, testing::Bool());
59 
TEST_P(ConfigUpdateE2eAbTest,TestUidMapVersionStringInstaller)60 TEST_P(ConfigUpdateE2eAbTest, TestUidMapVersionStringInstaller) {
61     sp<UidMap> uidMap = new UidMap();
62     UidData uidData;
63     ApplicationInfo appInfo = createApplicationInfo(/*uid*/ 1000, /*version*/ 1, "v1", "app1");
64     appInfo.set_installer("installer1");
65     *uidData.add_app_info() = appInfo;
66     uidMap->updateMap(1 /* timestamp */, uidData);
67 
68     StatsdConfig config = CreateSimpleConfig();
69     config.set_version_strings_in_metric_report(true);
70     config.set_installer_in_metric_report(false);
71     int64_t baseTimeNs = getElapsedRealtimeNs();
72 
73     ConfigKey cfgKey(0, 12345);
74     sp<StatsLogProcessor> processor =
75             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey, nullptr, 0, uidMap);
76     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
77     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
78     EXPECT_TRUE(metricsManager->isConfigValid());
79 
80     // Now update.
81     config.set_version_strings_in_metric_report(false);
82     config.set_installer_in_metric_report(true);
83     processor->OnConfigUpdated(baseTimeNs + 1000, cfgKey, config, GetParam());
84     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
85     EXPECT_EQ(metricsManager == processor->mMetricsManagers.begin()->second, GetParam());
86     EXPECT_TRUE(metricsManager->isConfigValid());
87 
88     ConfigMetricsReportList reports;
89     vector<uint8_t> buffer;
90     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
91     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
92     // First report is written to disk when the update happens.
93     ASSERT_EQ(reports.reports_size(), 2);
94     UidMapping uidMapping = reports.reports(1).uid_map();
95     ASSERT_EQ(uidMapping.snapshots_size(), 1);
96     ASSERT_EQ(uidMapping.snapshots(0).package_info_size(), 1);
97     EXPECT_FALSE(uidMapping.snapshots(0).package_info(0).has_version_string());
98     EXPECT_EQ(uidMapping.snapshots(0).package_info(0).installer_index(), 0);
99     EXPECT_THAT(uidMapping.installer_name(), ElementsAre("installer1"));
100 }
101 
TEST_P(ConfigUpdateE2eAbTest,TestHashStrings)102 TEST_P(ConfigUpdateE2eAbTest, TestHashStrings) {
103     sp<UidMap> uidMap = new UidMap();
104     UidData uidData;
105     ApplicationInfo appInfo = createApplicationInfo(/*uid*/ 1000, /*version*/ 1, "v1", "app1");
106     appInfo.set_installer("installer1");
107     *uidData.add_app_info() = appInfo;
108     uidMap->updateMap(1 /* timestamp */, uidData);
109 
110     StatsdConfig config = CreateSimpleConfig();
111     config.set_version_strings_in_metric_report(true);
112     config.set_hash_strings_in_metric_report(true);
113     int64_t baseTimeNs = getElapsedRealtimeNs();
114 
115     ConfigKey cfgKey(0, 12345);
116     sp<StatsLogProcessor> processor =
117             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey, nullptr, 0, uidMap);
118     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
119     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
120     EXPECT_TRUE(metricsManager->isConfigValid());
121 
122     // Now update.
123     config.set_hash_strings_in_metric_report(false);
124     processor->OnConfigUpdated(baseTimeNs + 1000, cfgKey, config, GetParam());
125     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
126     EXPECT_EQ(metricsManager == processor->mMetricsManagers.begin()->second, GetParam());
127     EXPECT_TRUE(metricsManager->isConfigValid());
128 
129     ConfigMetricsReportList reports;
130     vector<uint8_t> buffer;
131     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
132     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
133     // First report is written to disk when the update happens.
134     ASSERT_EQ(reports.reports_size(), 2);
135     UidMapping uidMapping = reports.reports(1).uid_map();
136     ASSERT_EQ(uidMapping.snapshots_size(), 1);
137     ASSERT_EQ(uidMapping.snapshots(0).package_info_size(), 1);
138     EXPECT_TRUE(uidMapping.snapshots(0).package_info(0).has_version_string());
139     EXPECT_FALSE(uidMapping.snapshots(0).package_info(0).has_version_string_hash());
140 }
141 
TEST_P(ConfigUpdateE2eAbTest,TestAnnotations)142 TEST_P(ConfigUpdateE2eAbTest, TestAnnotations) {
143     StatsdConfig config = CreateSimpleConfig();
144     StatsdConfig_Annotation* annotation = config.add_annotation();
145     annotation->set_field_int64(11);
146     annotation->set_field_int32(1);
147     int64_t baseTimeNs = getElapsedRealtimeNs();
148     ConfigKey cfgKey(0, 12345);
149     sp<StatsLogProcessor> processor =
150             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey);
151 
152     // Now update
153     config.clear_annotation();
154     annotation = config.add_annotation();
155     annotation->set_field_int64(22);
156     annotation->set_field_int32(2);
157     processor->OnConfigUpdated(baseTimeNs + 1000, cfgKey, config, GetParam());
158 
159     ConfigMetricsReportList reports;
160     vector<uint8_t> buffer;
161     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
162     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
163     // First report is written to disk when the update happens.
164     ASSERT_EQ(reports.reports_size(), 2);
165     ConfigMetricsReport report = reports.reports(1);
166     EXPECT_EQ(report.annotation_size(), 1);
167     EXPECT_EQ(report.annotation(0).field_int64(), 22);
168     EXPECT_EQ(report.annotation(0).field_int32(), 2);
169 }
170 
TEST_P(ConfigUpdateE2eAbTest,TestPersistLocally)171 TEST_P(ConfigUpdateE2eAbTest, TestPersistLocally) {
172     StatsdConfig config = CreateSimpleConfig();
173     config.set_persist_locally(false);
174     int64_t baseTimeNs = getElapsedRealtimeNs();
175     ConfigKey cfgKey(0, 12345);
176     sp<StatsLogProcessor> processor =
177             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey);
178     ConfigMetricsReportList reports;
179     vector<uint8_t> buffer;
180     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
181     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
182     ASSERT_EQ(reports.reports_size(), 1);
183     // Number of reports should still be 1 since persist_locally is false.
184     reports.Clear();
185     buffer.clear();
186     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
187     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
188     ASSERT_EQ(reports.reports_size(), 1);
189 
190     // Now update.
191     config.set_persist_locally(true);
192     processor->OnConfigUpdated(baseTimeNs + 1000, cfgKey, config, GetParam());
193 
194     // Should get 2: 1 in memory + 1 on disk. Both should be saved on disk.
195     reports.Clear();
196     buffer.clear();
197     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
198     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
199     ASSERT_EQ(reports.reports_size(), 2);
200     // Should get 3, 2 on disk + 1 in memory.
201     reports.Clear();
202     buffer.clear();
203     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
204     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
205     ASSERT_EQ(reports.reports_size(), 3);
206     string suffix = StringPrintf("%d_%lld", cfgKey.GetUid(), (long long)cfgKey.GetId());
207     StorageManager::deleteSuffixedFiles(STATS_DATA_DIR, suffix.c_str());
208     string historySuffix =
209             StringPrintf("%d_%lld_history", cfgKey.GetUid(), (long long)cfgKey.GetId());
210     StorageManager::deleteSuffixedFiles(STATS_DATA_DIR, historySuffix.c_str());
211 }
212 
TEST_P(ConfigUpdateE2eAbTest,TestNoReportMetrics)213 TEST_P(ConfigUpdateE2eAbTest, TestNoReportMetrics) {
214     StatsdConfig config = CreateSimpleConfig();
215     // Second simple count metric.
216     CountMetric* countMetric = config.add_count_metric();
217     countMetric->set_id(StringToId("Count2"));
218     countMetric->set_what(config.atom_matcher(0).id());
219     countMetric->set_bucket(FIVE_MINUTES);
220     config.add_no_report_metric(config.count_metric(0).id());
221     int64_t baseTimeNs = getElapsedRealtimeNs();
222     ConfigKey cfgKey(0, 12345);
223     sp<StatsLogProcessor> processor =
224             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey);
225 
226     // Now update.
227     config.clear_no_report_metric();
228     config.add_no_report_metric(config.count_metric(1).id());
229     processor->OnConfigUpdated(baseTimeNs + 1000, cfgKey, config, GetParam());
230 
231     ConfigMetricsReportList reports;
232     vector<uint8_t> buffer;
233     processor->onDumpReport(cfgKey, baseTimeNs + 1001, false, true, ADB_DUMP, FAST, &buffer);
234     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
235     // First report is written to disk when the update happens.
236     ASSERT_EQ(reports.reports_size(), 2);
237     // First report (before update) has the first count metric.
238     ASSERT_EQ(reports.reports(0).metrics_size(), 1);
239     EXPECT_EQ(reports.reports(0).metrics(0).metric_id(), config.count_metric(1).id());
240     // Second report (after update) has the first count metric.
241     ASSERT_EQ(reports.reports(1).metrics_size(), 1);
242     EXPECT_EQ(reports.reports(1).metrics(0).metric_id(), config.count_metric(0).id());
243 }
244 
TEST_P(ConfigUpdateE2eAbTest,TestAtomsAllowedFromAnyUid)245 TEST_P(ConfigUpdateE2eAbTest, TestAtomsAllowedFromAnyUid) {
246     StatsdConfig config = CreateSimpleConfig();
247     int64_t baseTimeNs = getElapsedRealtimeNs();
248     ConfigKey cfgKey(0, 12345);
249     sp<StatsLogProcessor> processor =
250             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey);
251     const int32_t customAppUid = AID_APP_START + 1;
252     // override default uid (which is user running the test)
253     unique_ptr<LogEvent> event = CreateBatteryStateChangedEvent(
254             baseTimeNs + 2, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB, customAppUid);
255     processor->OnLogEvent(event.get());
256     ConfigMetricsReportList reports;
257     vector<uint8_t> buffer;
258     processor->onDumpReport(cfgKey, baseTimeNs + 1001, true, true, ADB_DUMP, FAST, &buffer);
259     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
260     ASSERT_EQ(reports.reports_size(), 1);
261     // Check the metric and make sure it has 0 count.
262     ASSERT_EQ(reports.reports(0).metrics_size(), 1);
263     EXPECT_FALSE(reports.reports(0).metrics(0).has_count_metrics());
264 
265     // Now update. Allow plugged state to be logged from any uid, so the atom will be counted.
266     config.add_whitelisted_atom_ids(util::PLUGGED_STATE_CHANGED);
267     processor->OnConfigUpdated(baseTimeNs + 1000, cfgKey, config, GetParam());
268     unique_ptr<LogEvent> event2 = CreateBatteryStateChangedEvent(
269             baseTimeNs + 2000, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB);
270     processor->OnLogEvent(event.get());
271     reports.Clear();
272     buffer.clear();
273     processor->onDumpReport(cfgKey, baseTimeNs + 3000, true, true, ADB_DUMP, FAST, &buffer);
274     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
275     ASSERT_EQ(reports.reports_size(), 2);
276     // Check the metric and make sure it has 0 count.
277     ASSERT_EQ(reports.reports(1).metrics_size(), 1);
278     EXPECT_TRUE(reports.reports(1).metrics(0).has_count_metrics());
279     ASSERT_EQ(reports.reports(1).metrics(0).count_metrics().data_size(), 1);
280     ASSERT_EQ(reports.reports(1).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
281     EXPECT_EQ(reports.reports(1).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
282 }
283 
TEST_P(ConfigUpdateE2eAbTest,TestConfigTtl)284 TEST_P(ConfigUpdateE2eAbTest, TestConfigTtl) {
285     StatsdConfig config = CreateSimpleConfig();
286     config.set_ttl_in_seconds(1);
287     int64_t baseTimeNs = getElapsedRealtimeNs();
288     ConfigKey cfgKey(0, 12345);
289     sp<StatsLogProcessor> processor =
290             CreateStatsLogProcessor(baseTimeNs, baseTimeNs, config, cfgKey);
291     EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
292     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
293     EXPECT_EQ(metricsManager->getTtlEndNs(), baseTimeNs + NS_PER_SEC);
294 
295     config.set_ttl_in_seconds(5);
296     processor->OnConfigUpdated(baseTimeNs + 2 * NS_PER_SEC, cfgKey, config, GetParam());
297     metricsManager = processor->mMetricsManagers.begin()->second;
298     EXPECT_EQ(metricsManager->getTtlEndNs(), baseTimeNs + 7 * NS_PER_SEC);
299 
300     // Clear the data stored on disk as a result of the update.
301     vector<uint8_t> buffer;
302     processor->onDumpReport(cfgKey, baseTimeNs + 3 * NS_PER_SEC, false, true, ADB_DUMP, FAST,
303                             &buffer);
304 }
305 
TEST_P(ConfigUpdateE2eAbTest,TestExistingGaugePullRandomOneSample)306 TEST_P(ConfigUpdateE2eAbTest, TestExistingGaugePullRandomOneSample) {
307     StatsdConfig config;
308     config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
309 
310     AtomMatcher subsystemSleepMatcher =
311             CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE);
312     *config.add_atom_matcher() = subsystemSleepMatcher;
313 
314     GaugeMetric metric = createGaugeMetric("GaugeSubsystemSleep", subsystemSleepMatcher.id(),
315                                            GaugeMetric::RANDOM_ONE_SAMPLE, nullopt, nullopt);
316     *metric.mutable_dimensions_in_what() =
317             CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
318     *config.add_gauge_metric() = metric;
319 
320     ConfigKey key(123, 987);
321     uint64_t bucketStartTimeNs = getElapsedRealtimeNs();
322     uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
323     sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
324             bucketStartTimeNs, bucketStartTimeNs, config, key,
325             SharedRefBase::make<FakeSubsystemSleepCallback>(), util::SUBSYSTEM_SLEEP_STATE);
326 
327     uint64_t updateTimeNs = bucketStartTimeNs + 60 * NS_PER_SEC;
328     processor->OnConfigUpdated(updateTimeNs, key, config, GetParam());
329     uint64_t dumpTimeNs = bucketStartTimeNs + 90 * NS_PER_SEC;
330     ConfigMetricsReportList reports;
331     vector<uint8_t> buffer;
332     processor->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
333     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
334     backfillDimensionPath(&reports);
335     backfillStringInReport(&reports);
336     backfillStartEndTimestamp(&reports);
337     backfillAggregatedAtoms(&reports);
338     ASSERT_EQ(reports.reports_size(), 2);
339 
340     // From after the update
341     ConfigMetricsReport report = reports.reports(1);
342     ASSERT_EQ(report.metrics_size(), 1);
343     // Count screen on while screen is on. There was 1 after the update.
344     StatsLogReport metricData = report.metrics(0);
345     EXPECT_EQ(metricData.metric_id(), metric.id());
346     EXPECT_TRUE(metricData.has_gauge_metrics());
347     StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
348     sortMetricDataByDimensionsValue(metricData.gauge_metrics(), &gaugeMetrics);
349     ASSERT_EQ(gaugeMetrics.data_size(), 2);
350 
351     GaugeMetricData data = metricData.gauge_metrics().data(0);
352     EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
353     ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
354     EXPECT_EQ(1 /* subsystem name field */,
355               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
356     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(),
357               "subsystem_name_1");
358     ASSERT_EQ(data.bucket_info_size(), 1);
359     ASSERT_EQ(1, data.bucket_info(0).atom_size());
360     ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
361     EXPECT_EQ(updateTimeNs, data.bucket_info(0).elapsed_timestamp_nanos(0));
362     EXPECT_EQ(MillisToNano(NanoToMillis(updateTimeNs)),
363               data.bucket_info(0).start_bucket_elapsed_nanos());
364     EXPECT_EQ(MillisToNano(NanoToMillis(dumpTimeNs)),
365               data.bucket_info(0).end_bucket_elapsed_nanos());
366     EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
367     EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
368 }
369 
370 #else
371 GTEST_LOG_(INFO) << "This test does nothing.\n";
372 #endif
373 
374 }  // namespace statsd
375 }  // namespace os
376 }  // namespace android
377