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