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