• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 #include <private/android_filesystem_config.h>
18 #include <stdio.h>
19 
20 #include <set>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "metrics/metrics_test_helper.h"
25 #include "src/condition/ConditionTracker.h"
26 #include "src/matchers/AtomMatchingTracker.h"
27 #include "src/metrics/CountMetricProducer.h"
28 #include "src/metrics/GaugeMetricProducer.h"
29 #include "src/metrics/MetricProducer.h"
30 #include "src/metrics/NumericValueMetricProducer.h"
31 #include "src/metrics/parsing_utils/metrics_manager_util.h"
32 #include "src/state/StateManager.h"
33 #include "src/statsd_config.pb.h"
34 #include "statsd_test_util.h"
35 
36 using namespace testing;
37 using android::sp;
38 using android::modules::sdklevel::IsAtLeastS;
39 using android::modules::sdklevel::IsAtLeastU;
40 using android::os::statsd::Predicate;
41 using std::map;
42 using std::set;
43 using std::unordered_map;
44 using std::vector;
45 
46 #ifdef __ANDROID__
47 
48 namespace android {
49 namespace os {
50 namespace statsd {
51 
52 namespace {
53 const ConfigKey kConfigKey(0, 12345);
54 
55 const long timeBaseSec = 1000;
56 
buildGoodConfig()57 StatsdConfig buildGoodConfig() {
58     StatsdConfig config;
59     config.set_id(12345);
60 
61     AtomMatcher* eventMatcher = config.add_atom_matcher();
62     eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
63 
64     SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
65     simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
66     simpleAtomMatcher->add_field_value_matcher()->set_field(
67             1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
68     simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
69             2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
70 
71     eventMatcher = config.add_atom_matcher();
72     eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
73 
74     simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
75     simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
76     simpleAtomMatcher->add_field_value_matcher()->set_field(
77             1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
78     simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
79             1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
80 
81     eventMatcher = config.add_atom_matcher();
82     eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
83 
84     AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
85     combination->set_operation(LogicalOperation::OR);
86     combination->add_matcher(StringToId("SCREEN_IS_ON"));
87     combination->add_matcher(StringToId("SCREEN_IS_OFF"));
88 
89     CountMetric* metric = config.add_count_metric();
90     metric->set_id(3);
91     metric->set_what(StringToId("SCREEN_IS_ON"));
92     metric->set_bucket(ONE_MINUTE);
93     metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
94     metric->mutable_dimensions_in_what()->add_child()->set_field(1);
95     return config;
96 }
97 
buildGoodRestrictedConfig()98 StatsdConfig buildGoodRestrictedConfig() {
99     StatsdConfig config;
100     config.set_id(12345);
101     config.set_restricted_metrics_delegate_package_name("delegate");
102 
103     AtomMatcher* eventMatcher = config.add_atom_matcher();
104     eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
105     SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
106     simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
107 
108     EventMetric* metric = config.add_event_metric();
109     metric->set_id(3);
110     metric->set_what(StringToId("SCREEN_IS_ON"));
111     return config;
112 }
113 
unionSet(const vector<set<int32_t>> sets)114 set<int32_t> unionSet(const vector<set<int32_t>> sets) {
115     set<int32_t> toRet;
116     for (const set<int32_t>& s : sets) {
117         toRet.insert(s.begin(), s.end());
118     }
119     return toRet;
120 }
121 }  // anonymous namespace
122 
TEST(MetricsManagerTest,TestLogSources)123 TEST(MetricsManagerTest, TestLogSources) {
124     string app1 = "app1";
125     set<int32_t> app1Uids = {1111, 11111};
126     string app2 = "app2";
127     set<int32_t> app2Uids = {2222};
128     string app3 = "app3";
129     set<int32_t> app3Uids = {3333, 1111};
130 
131     map<string, set<int32_t>> pkgToUids;
132     pkgToUids[app1] = app1Uids;
133     pkgToUids[app2] = app2Uids;
134     pkgToUids[app3] = app3Uids;
135 
136     int32_t atom1 = 10, atom2 = 20, atom3 = 30;
137     sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
138     EXPECT_CALL(*uidMap, getAppUid(_))
139             .Times(4)
140             .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) {
141                 const auto& it = pkgToUids.find(pkg);
142                 if (it != pkgToUids.end()) {
143                     return it->second;
144                 }
145                 return set<int32_t>();
146             }));
147     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
148     EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
149     EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
150 
151     sp<AlarmMonitor> anomalyAlarmMonitor;
152     sp<AlarmMonitor> periodicAlarmMonitor;
153 
154     StatsdConfig config;
155     config.add_allowed_log_source("AID_SYSTEM");
156     config.add_allowed_log_source(app1);
157     config.add_default_pull_packages("AID_SYSTEM");
158     config.add_default_pull_packages("AID_ROOT");
159 
160     const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_ROOT};
161 
162     PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages();
163     pullAtomPackages->set_atom_id(atom1);
164     pullAtomPackages->add_packages(app1);
165     pullAtomPackages->add_packages(app3);
166 
167     pullAtomPackages = config.add_pull_atom_packages();
168     pullAtomPackages->set_atom_id(atom2);
169     pullAtomPackages->add_packages(app2);
170     pullAtomPackages->add_packages("AID_STATSD");
171 
172     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
173                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
174     EXPECT_TRUE(metricsManager.isConfigValid());
175 
176     EXPECT_THAT(metricsManager.mAllowedUid, ElementsAre(AID_SYSTEM));
177     EXPECT_THAT(metricsManager.mAllowedPkg, ElementsAre(app1));
178     EXPECT_THAT(metricsManager.mAllowedLogSources,
179                 ContainerEq(unionSet(vector<set<int32_t>>({app1Uids, {AID_SYSTEM}}))));
180     EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids));
181 
182     vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
183     EXPECT_THAT(atom1Uids,
184                 UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids})));
185 
186     vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
187     EXPECT_THAT(atom2Uids,
188                 UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_STATSD}})));
189 
190     vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
191     EXPECT_THAT(atom3Uids, UnorderedElementsAreArray(defaultPullUids));
192 }
193 
TEST(MetricsManagerTest,TestLogSourcesOnConfigUpdate)194 TEST(MetricsManagerTest, TestLogSourcesOnConfigUpdate) {
195     string app1 = "app1";
196     set<int32_t> app1Uids = {1111, 11111};
197     string app2 = "app2";
198     set<int32_t> app2Uids = {2222};
199     string app3 = "app3";
200     set<int32_t> app3Uids = {3333, 1111};
201 
202     map<string, set<int32_t>> pkgToUids;
203     pkgToUids[app1] = app1Uids;
204     pkgToUids[app2] = app2Uids;
205     pkgToUids[app3] = app3Uids;
206 
207     int32_t atom1 = 10, atom2 = 20, atom3 = 30;
208     sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
209     EXPECT_CALL(*uidMap, getAppUid(_))
210             .Times(8)
211             .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) {
212                 const auto& it = pkgToUids.find(pkg);
213                 if (it != pkgToUids.end()) {
214                     return it->second;
215                 }
216                 return set<int32_t>();
217             }));
218     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
219     EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
220     EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
221 
222     sp<AlarmMonitor> anomalyAlarmMonitor;
223     sp<AlarmMonitor> periodicAlarmMonitor;
224 
225     StatsdConfig config;
226     config.add_allowed_log_source("AID_SYSTEM");
227     config.add_allowed_log_source(app1);
228     config.add_default_pull_packages("AID_SYSTEM");
229     config.add_default_pull_packages("AID_ROOT");
230 
231     PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages();
232     pullAtomPackages->set_atom_id(atom1);
233     pullAtomPackages->add_packages(app1);
234     pullAtomPackages->add_packages(app3);
235 
236     pullAtomPackages = config.add_pull_atom_packages();
237     pullAtomPackages->set_atom_id(atom2);
238     pullAtomPackages->add_packages(app2);
239     pullAtomPackages->add_packages("AID_STATSD");
240 
241     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
242                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
243     EXPECT_TRUE(metricsManager.isConfigValid());
244 
245     // Update with new allowed log sources.
246     StatsdConfig newConfig;
247     newConfig.add_allowed_log_source("AID_ROOT");
248     newConfig.add_allowed_log_source(app2);
249     newConfig.add_default_pull_packages("AID_SYSTEM");
250     newConfig.add_default_pull_packages("AID_STATSD");
251 
252     pullAtomPackages = newConfig.add_pull_atom_packages();
253     pullAtomPackages->set_atom_id(atom2);
254     pullAtomPackages->add_packages(app1);
255     pullAtomPackages->add_packages(app3);
256 
257     pullAtomPackages = newConfig.add_pull_atom_packages();
258     pullAtomPackages->set_atom_id(atom3);
259     pullAtomPackages->add_packages(app2);
260     pullAtomPackages->add_packages("AID_ADB");
261 
262     metricsManager.updateConfig(newConfig, timeBaseSec, timeBaseSec, anomalyAlarmMonitor,
263                                 periodicAlarmMonitor);
264     EXPECT_TRUE(metricsManager.isConfigValid());
265 
266     EXPECT_THAT(metricsManager.mAllowedUid, ElementsAre(AID_ROOT));
267     EXPECT_THAT(metricsManager.mAllowedPkg, ElementsAre(app2));
268     EXPECT_THAT(metricsManager.mAllowedLogSources,
269                 ContainerEq(unionSet(vector<set<int32_t>>({app2Uids, {AID_ROOT}}))));
270     const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_STATSD};
271     EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids));
272 
273     vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
274     EXPECT_THAT(atom1Uids, UnorderedElementsAreArray(defaultPullUids));
275 
276     vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
277     EXPECT_THAT(atom2Uids,
278                 UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids})));
279 
280     vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
281     EXPECT_THAT(atom3Uids,
282                 UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_ADB}})));
283 }
284 
285 struct MetricsManagerServerFlagParam {
286     string flagValue;
287     string label;
288 };
289 
290 class MetricsManagerTest_SPlus
291     : public ::testing::Test,
292       public ::testing::WithParamInterface<MetricsManagerServerFlagParam> {
293 protected:
SetUp()294     void SetUp() override {
295         if (shouldSkipTest()) {
296             GTEST_SKIP() << skipReason();
297         }
298     }
299 
shouldSkipTest() const300     bool shouldSkipTest() const {
301         return !IsAtLeastS();
302     }
303 
skipReason() const304     string skipReason() const {
305         return "Skipping MetricsManagerTest_SPlus because device is not S+";
306     }
307 
308     std::optional<string> originalFlagValue;
309 };
310 
311 INSTANTIATE_TEST_SUITE_P(
312         MetricsManagerTest_SPlus, MetricsManagerTest_SPlus,
313         testing::ValuesIn<MetricsManagerServerFlagParam>({
314                 // Server flag values
315                 {FLAG_TRUE, "ServerFlagTrue"},
316                 {FLAG_FALSE, "ServerFlagFalse"},
317         }),
__anonee29e5420402(const testing::TestParamInfo<MetricsManagerTest_SPlus::ParamType>& info) 318         [](const testing::TestParamInfo<MetricsManagerTest_SPlus::ParamType>& info) {
319             return info.param.label;
320         });
321 
TEST(MetricsManagerTest,TestCheckLogCredentialsWhitelistedAtom)322 TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
323     sp<UidMap> uidMap;
324     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
325     sp<AlarmMonitor> anomalyAlarmMonitor;
326     sp<AlarmMonitor> periodicAlarmMonitor;
327 
328     StatsdConfig config;
329     config.add_whitelisted_atom_ids(3);
330     config.add_whitelisted_atom_ids(4);
331 
332     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
333                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
334 
335     LogEvent event(0 /* uid */, 0 /* pid */);
336     CreateNoValuesLogEvent(&event, 10 /* atom id */, 0 /* timestamp */);
337     EXPECT_FALSE(metricsManager.checkLogCredentials(event));
338 
339     CreateNoValuesLogEvent(&event, 3 /* atom id */, 0 /* timestamp */);
340     EXPECT_TRUE(metricsManager.checkLogCredentials(event));
341 
342     CreateNoValuesLogEvent(&event, 4 /* atom id */, 0 /* timestamp */);
343     EXPECT_TRUE(metricsManager.checkLogCredentials(event));
344 }
345 
TEST(MetricsManagerTest,TestWhitelistedAtomStateTracker)346 TEST(MetricsManagerTest, TestWhitelistedAtomStateTracker) {
347     sp<UidMap> uidMap;
348     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
349     sp<AlarmMonitor> anomalyAlarmMonitor;
350     sp<AlarmMonitor> periodicAlarmMonitor;
351 
352     StatsdConfig config = buildGoodConfig();
353     config.add_allowed_log_source("AID_SYSTEM");
354     config.add_whitelisted_atom_ids(3);
355     config.add_whitelisted_atom_ids(4);
356 
357     State state;
358     state.set_id(1);
359     state.set_atom_id(3);
360 
361     *config.add_state() = state;
362 
363     config.mutable_count_metric(0)->add_slice_by_state(state.id());
364 
365     StateManager::getInstance().clear();
366 
367     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
368                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
369 
370     EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
371     EXPECT_FALSE(metricsManager.isConfigValid());
372 }
373 
TEST_P(MetricsManagerTest_SPlus,TestRestrictedMetricsConfig)374 TEST_P(MetricsManagerTest_SPlus, TestRestrictedMetricsConfig) {
375     sp<UidMap> uidMap;
376     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
377     sp<AlarmMonitor> anomalyAlarmMonitor;
378     sp<AlarmMonitor> periodicAlarmMonitor;
379 
380     StatsdConfig config = buildGoodRestrictedConfig();
381     config.add_allowed_log_source("AID_SYSTEM");
382     config.set_restricted_metrics_delegate_package_name("rm");
383 
384     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
385                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
386 
387     if (IsAtLeastU()) {
388         EXPECT_TRUE(metricsManager.isConfigValid());
389     } else {
390         EXPECT_EQ(metricsManager.mInvalidConfigReason,
391                   INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_ENABLED);
392         ASSERT_FALSE(metricsManager.isConfigValid());
393     }
394 }
395 
TEST_P(MetricsManagerTest_SPlus,TestRestrictedMetricsConfigUpdate)396 TEST_P(MetricsManagerTest_SPlus, TestRestrictedMetricsConfigUpdate) {
397     sp<UidMap> uidMap;
398     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
399     sp<AlarmMonitor> anomalyAlarmMonitor;
400     sp<AlarmMonitor> periodicAlarmMonitor;
401 
402     StatsdConfig config = buildGoodRestrictedConfig();
403     config.add_allowed_log_source("AID_SYSTEM");
404     config.set_restricted_metrics_delegate_package_name("rm");
405 
406     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
407                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
408 
409     StatsdConfig config2 = buildGoodRestrictedConfig();
410     metricsManager.updateConfig(config, timeBaseSec, timeBaseSec, anomalyAlarmMonitor,
411                                 periodicAlarmMonitor);
412 
413     if (IsAtLeastU()) {
414         EXPECT_TRUE(metricsManager.isConfigValid());
415     } else {
416         EXPECT_EQ(metricsManager.mInvalidConfigReason,
417                   INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_ENABLED);
418         ASSERT_FALSE(metricsManager.isConfigValid());
419     }
420 }
421 
422 }  // namespace statsd
423 }  // namespace os
424 }  // namespace android
425 
426 #else
427 GTEST_LOG_(INFO) << "This test does nothing.\n";
428 #endif
429