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