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 "src/statsd_config.pb.h"
25 #include "metrics/metrics_test_helper.h"
26 #include "src/condition/ConditionTracker.h"
27 #include "src/matchers/AtomMatchingTracker.h"
28 #include "src/metrics/CountMetricProducer.h"
29 #include "src/metrics/GaugeMetricProducer.h"
30 #include "src/metrics/MetricProducer.h"
31 #include "src/metrics/ValueMetricProducer.h"
32 #include "src/metrics/parsing_utils/metrics_manager_util.h"
33 #include "src/state/StateManager.h"
34 #include "statsd_test_util.h"
35 
36 using namespace testing;
37 using android::sp;
38 using android::os::statsd::Predicate;
39 using std::map;
40 using std::set;
41 using std::unordered_map;
42 using std::vector;
43 
44 #ifdef __ANDROID__
45 
46 namespace android {
47 namespace os {
48 namespace statsd {
49 
50 namespace {
51 const ConfigKey kConfigKey(0, 12345);
52 
53 const long timeBaseSec = 1000;
54 
buildGoodConfig()55 StatsdConfig buildGoodConfig() {
56     StatsdConfig config;
57     config.set_id(12345);
58 
59     AtomMatcher* eventMatcher = config.add_atom_matcher();
60     eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
61 
62     SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
63     simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
64     simpleAtomMatcher->add_field_value_matcher()->set_field(
65             1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
66     simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
67             2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
68 
69     eventMatcher = config.add_atom_matcher();
70     eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
71 
72     simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
73     simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
74     simpleAtomMatcher->add_field_value_matcher()->set_field(
75             1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
76     simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
77             1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
78 
79     eventMatcher = config.add_atom_matcher();
80     eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
81 
82     AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
83     combination->set_operation(LogicalOperation::OR);
84     combination->add_matcher(StringToId("SCREEN_IS_ON"));
85     combination->add_matcher(StringToId("SCREEN_IS_OFF"));
86 
87     CountMetric* metric = config.add_count_metric();
88     metric->set_id(3);
89     metric->set_what(StringToId("SCREEN_IS_ON"));
90     metric->set_bucket(ONE_MINUTE);
91     metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
92     metric->mutable_dimensions_in_what()->add_child()->set_field(1);
93     return config;
94 }
95 
unionSet(const vector<set<int32_t>> sets)96 set<int32_t> unionSet(const vector<set<int32_t>> sets) {
97     set<int32_t> toRet;
98     for (const set<int32_t>& s : sets) {
99         toRet.insert(s.begin(), s.end());
100     }
101     return toRet;
102 }
103 }  // anonymous namespace
104 
TEST(MetricsManagerTest,TestLogSources)105 TEST(MetricsManagerTest, TestLogSources) {
106     string app1 = "app1";
107     set<int32_t> app1Uids = {1111, 11111};
108     string app2 = "app2";
109     set<int32_t> app2Uids = {2222};
110     string app3 = "app3";
111     set<int32_t> app3Uids = {3333, 1111};
112 
113     map<string, set<int32_t>> pkgToUids;
114     pkgToUids[app1] = app1Uids;
115     pkgToUids[app2] = app2Uids;
116     pkgToUids[app3] = app3Uids;
117 
118     int32_t atom1 = 10, atom2 = 20, atom3 = 30;
119     sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
120     EXPECT_CALL(*uidMap, getAppUid(_))
121             .Times(4)
122             .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) {
123                 const auto& it = pkgToUids.find(pkg);
124                 if (it != pkgToUids.end()) {
125                     return it->second;
126                 }
127                 return set<int32_t>();
128             }));
129     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
130     EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
131     EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
132 
133     sp<AlarmMonitor> anomalyAlarmMonitor;
134     sp<AlarmMonitor> periodicAlarmMonitor;
135 
136     StatsdConfig config;
137     config.add_allowed_log_source("AID_SYSTEM");
138     config.add_allowed_log_source(app1);
139     config.add_default_pull_packages("AID_SYSTEM");
140     config.add_default_pull_packages("AID_ROOT");
141 
142     const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_ROOT};
143 
144     PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages();
145     pullAtomPackages->set_atom_id(atom1);
146     pullAtomPackages->add_packages(app1);
147     pullAtomPackages->add_packages(app3);
148 
149     pullAtomPackages = config.add_pull_atom_packages();
150     pullAtomPackages->set_atom_id(atom2);
151     pullAtomPackages->add_packages(app2);
152     pullAtomPackages->add_packages("AID_STATSD");
153 
154     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
155                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
156     EXPECT_TRUE(metricsManager.isConfigValid());
157 
158     EXPECT_THAT(metricsManager.mAllowedUid, ElementsAre(AID_SYSTEM));
159     EXPECT_THAT(metricsManager.mAllowedPkg, ElementsAre(app1));
160     EXPECT_THAT(metricsManager.mAllowedLogSources,
161                 ContainerEq(unionSet(vector<set<int32_t>>({app1Uids, {AID_SYSTEM}}))));
162     EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids));
163 
164     vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
165     EXPECT_THAT(atom1Uids,
166                 UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids})));
167 
168     vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
169     EXPECT_THAT(atom2Uids,
170                 UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_STATSD}})));
171 
172     vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
173     EXPECT_THAT(atom3Uids, UnorderedElementsAreArray(defaultPullUids));
174 }
175 
TEST(MetricsManagerTest,TestLogSourcesOnConfigUpdate)176 TEST(MetricsManagerTest, TestLogSourcesOnConfigUpdate) {
177     string app1 = "app1";
178     set<int32_t> app1Uids = {1111, 11111};
179     string app2 = "app2";
180     set<int32_t> app2Uids = {2222};
181     string app3 = "app3";
182     set<int32_t> app3Uids = {3333, 1111};
183 
184     map<string, set<int32_t>> pkgToUids;
185     pkgToUids[app1] = app1Uids;
186     pkgToUids[app2] = app2Uids;
187     pkgToUids[app3] = app3Uids;
188 
189     int32_t atom1 = 10, atom2 = 20, atom3 = 30;
190     sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
191     EXPECT_CALL(*uidMap, getAppUid(_))
192             .Times(8)
193             .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) {
194                 const auto& it = pkgToUids.find(pkg);
195                 if (it != pkgToUids.end()) {
196                     return it->second;
197                 }
198                 return set<int32_t>();
199             }));
200     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
201     EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
202     EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
203 
204     sp<AlarmMonitor> anomalyAlarmMonitor;
205     sp<AlarmMonitor> periodicAlarmMonitor;
206 
207     StatsdConfig config;
208     config.add_allowed_log_source("AID_SYSTEM");
209     config.add_allowed_log_source(app1);
210     config.add_default_pull_packages("AID_SYSTEM");
211     config.add_default_pull_packages("AID_ROOT");
212 
213     PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages();
214     pullAtomPackages->set_atom_id(atom1);
215     pullAtomPackages->add_packages(app1);
216     pullAtomPackages->add_packages(app3);
217 
218     pullAtomPackages = config.add_pull_atom_packages();
219     pullAtomPackages->set_atom_id(atom2);
220     pullAtomPackages->add_packages(app2);
221     pullAtomPackages->add_packages("AID_STATSD");
222 
223     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
224                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
225     EXPECT_TRUE(metricsManager.isConfigValid());
226 
227     // Update with new allowed log sources.
228     StatsdConfig newConfig;
229     newConfig.add_allowed_log_source("AID_ROOT");
230     newConfig.add_allowed_log_source(app2);
231     newConfig.add_default_pull_packages("AID_SYSTEM");
232     newConfig.add_default_pull_packages("AID_STATSD");
233 
234     pullAtomPackages = newConfig.add_pull_atom_packages();
235     pullAtomPackages->set_atom_id(atom2);
236     pullAtomPackages->add_packages(app1);
237     pullAtomPackages->add_packages(app3);
238 
239     pullAtomPackages = newConfig.add_pull_atom_packages();
240     pullAtomPackages->set_atom_id(atom3);
241     pullAtomPackages->add_packages(app2);
242     pullAtomPackages->add_packages("AID_ADB");
243 
244     metricsManager.updateConfig(newConfig, timeBaseSec, timeBaseSec, anomalyAlarmMonitor,
245                                 periodicAlarmMonitor);
246     EXPECT_TRUE(metricsManager.isConfigValid());
247 
248     EXPECT_THAT(metricsManager.mAllowedUid, ElementsAre(AID_ROOT));
249     EXPECT_THAT(metricsManager.mAllowedPkg, ElementsAre(app2));
250     EXPECT_THAT(metricsManager.mAllowedLogSources,
251                 ContainerEq(unionSet(vector<set<int32_t>>({app2Uids, {AID_ROOT}}))));
252     const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_STATSD};
253     EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids));
254 
255     vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
256     EXPECT_THAT(atom1Uids, UnorderedElementsAreArray(defaultPullUids));
257 
258     vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
259     EXPECT_THAT(atom2Uids,
260                 UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids})));
261 
262     vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
263     EXPECT_THAT(atom3Uids,
264                 UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_ADB}})));
265 }
266 
TEST(MetricsManagerTest,TestCheckLogCredentialsWhitelistedAtom)267 TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
268     sp<UidMap> uidMap;
269     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
270     sp<AlarmMonitor> anomalyAlarmMonitor;
271     sp<AlarmMonitor> periodicAlarmMonitor;
272 
273     StatsdConfig config;
274     config.add_whitelisted_atom_ids(3);
275     config.add_whitelisted_atom_ids(4);
276 
277     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
278                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
279 
280     LogEvent event(0 /* uid */, 0 /* pid */);
281     CreateNoValuesLogEvent(&event, 10 /* atom id */, 0 /* timestamp */);
282     EXPECT_FALSE(metricsManager.checkLogCredentials(event));
283 
284     CreateNoValuesLogEvent(&event, 3 /* atom id */, 0 /* timestamp */);
285     EXPECT_TRUE(metricsManager.checkLogCredentials(event));
286 
287     CreateNoValuesLogEvent(&event, 4 /* atom id */, 0 /* timestamp */);
288     EXPECT_TRUE(metricsManager.checkLogCredentials(event));
289 }
290 
TEST(MetricsManagerTest,TestWhitelistedAtomStateTracker)291 TEST(MetricsManagerTest, TestWhitelistedAtomStateTracker) {
292     sp<UidMap> uidMap;
293     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
294     sp<AlarmMonitor> anomalyAlarmMonitor;
295     sp<AlarmMonitor> periodicAlarmMonitor;
296 
297     StatsdConfig config = buildGoodConfig();
298     config.add_allowed_log_source("AID_SYSTEM");
299     config.add_whitelisted_atom_ids(3);
300     config.add_whitelisted_atom_ids(4);
301 
302     State state;
303     state.set_id(1);
304     state.set_atom_id(3);
305 
306     *config.add_state() = state;
307 
308     config.mutable_count_metric(0)->add_slice_by_state(state.id());
309 
310     StateManager::getInstance().clear();
311 
312     MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
313                                   pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
314 
315     EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
316     EXPECT_FALSE(metricsManager.isConfigValid());
317 }
318 
319 }  // namespace statsd
320 }  // namespace os
321 }  // namespace android
322 
323 #else
324 GTEST_LOG_(INFO) << "This test does nothing.\n";
325 #endif
326