1 // Copyright (C) 2023 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 <gtest/gtest.h>
16
17 #include "flags/FlagProvider.h"
18 #include "storage/StorageManager.h"
19 #include "tests/statsd_test_util.h"
20
21 namespace android {
22 namespace os {
23 namespace statsd {
24
25 #ifdef __ANDROID__
26
27 namespace {
28 const int32_t atomTag = 666;
29 const string delegatePackageName = "com.test.restricted.metrics.package";
30 const int32_t delegateUid = 10200;
31 const string configPackageName = "com.test.config.package";
32 int64_t metricId;
33 int64_t anotherMetricId;
34
CreateConfigWithOneMetric()35 StatsdConfig CreateConfigWithOneMetric() {
36 StatsdConfig config;
37 AtomMatcher atomMatcher = CreateSimpleAtomMatcher("testmatcher", atomTag);
38 *config.add_atom_matcher() = atomMatcher;
39
40 EventMetric eventMetric = createEventMetric("EventMetric", atomMatcher.id(), nullopt);
41 metricId = eventMetric.id();
42 *config.add_event_metric() = eventMetric;
43 return config;
44 }
CreateConfigWithTwoMetrics()45 StatsdConfig CreateConfigWithTwoMetrics() {
46 StatsdConfig config;
47 AtomMatcher atomMatcher = CreateSimpleAtomMatcher("testmatcher", atomTag);
48 *config.add_atom_matcher() = atomMatcher;
49
50 EventMetric eventMetric = createEventMetric("EventMetric", atomMatcher.id(), nullopt);
51 metricId = eventMetric.id();
52 *config.add_event_metric() = eventMetric;
53 EventMetric anotherEventMetric =
54 createEventMetric("AnotherEventMetric", atomMatcher.id(), nullopt);
55 anotherMetricId = anotherEventMetric.id();
56 *config.add_event_metric() = anotherEventMetric;
57 return config;
58 }
59
CreateLogEvents(int64_t configAddedTimeNs)60 std::vector<std::unique_ptr<LogEvent>> CreateLogEvents(int64_t configAddedTimeNs) {
61 std::vector<std::unique_ptr<LogEvent>> events;
62 events.push_back(CreateNonRestrictedLogEvent(atomTag, configAddedTimeNs + 10 * NS_PER_SEC));
63 events.push_back(CreateNonRestrictedLogEvent(atomTag, configAddedTimeNs + 20 * NS_PER_SEC));
64 events.push_back(CreateNonRestrictedLogEvent(atomTag, configAddedTimeNs + 30 * NS_PER_SEC));
65 return events;
66 }
67
68 } // Anonymous namespace
69
70 class RestrictedConfigE2ETest : public StatsServiceConfigTest {
71 protected:
72 shared_ptr<MockStatsQueryCallback> mockStatsQueryCallback;
73 const ConfigKey configKey = ConfigKey(kCallingUid, kConfigKey);
74 vector<string> queryDataResult;
75 vector<string> columnNamesResult;
76 vector<int32_t> columnTypesResult;
77 int32_t rowCountResult = 0;
78 string error;
79
SetUp()80 void SetUp() override {
81 if (!isAtLeastU()) {
82 GTEST_SKIP();
83 }
84 StatsServiceConfigTest::SetUp();
85
86 mockStatsQueryCallback = SharedRefBase::make<StrictMock<MockStatsQueryCallback>>();
87 EXPECT_CALL(*mockStatsQueryCallback, sendResults(_, _, _, _))
88 .Times(AnyNumber())
89 .WillRepeatedly(Invoke(
90 [this](const vector<string>& queryData, const vector<string>& columnNames,
91 const vector<int32_t>& columnTypes, int32_t rowCount) {
92 queryDataResult = queryData;
93 columnNamesResult = columnNames;
94 columnTypesResult = columnTypes;
95 rowCountResult = rowCount;
96 error = "";
97 return Status::ok();
98 }));
99 EXPECT_CALL(*mockStatsQueryCallback, sendFailure(_))
100 .Times(AnyNumber())
101 .WillRepeatedly(Invoke([this](const string& err) {
102 error = err;
103 queryDataResult.clear();
104 columnNamesResult.clear();
105 columnTypesResult.clear();
106 rowCountResult = 0;
107 return Status::ok();
108 }));
109
110 int64_t startTimeNs = getElapsedRealtimeNs();
111 UidData uidData;
112 *uidData.add_app_info() = createApplicationInfo(delegateUid, 1, "v2", delegatePackageName);
113 *uidData.add_app_info() = createApplicationInfo(kCallingUid, 1, "v2", configPackageName);
114 service->mUidMap->updateMap(startTimeNs, uidData);
115 }
TearDown()116 void TearDown() override {
117 if (!isAtLeastU()) {
118 GTEST_SKIP();
119 }
120 Mock::VerifyAndClear(mockStatsQueryCallback.get());
121 queryDataResult.clear();
122 columnNamesResult.clear();
123 columnTypesResult.clear();
124 rowCountResult = 0;
125 error = "";
126 StatsServiceConfigTest::TearDown();
127 FlagProvider::getInstance().resetOverrides();
128 dbutils::deleteDb(configKey);
129 }
130
verifyRestrictedData(int32_t expectedNumOfMetrics,int64_t metricIdToVerify=metricId,bool shouldExist=true)131 void verifyRestrictedData(int32_t expectedNumOfMetrics, int64_t metricIdToVerify = metricId,
132 bool shouldExist = true) {
133 std::stringstream query;
134 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(metricIdToVerify);
135 string err;
136 std::vector<int32_t> columnTypes;
137 std::vector<string> columnNames;
138 std::vector<std::vector<std::string>> rows;
139 if (shouldExist) {
140 EXPECT_TRUE(
141 dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
142 EXPECT_EQ(rows.size(), expectedNumOfMetrics);
143 } else {
144 // Expect that table is deleted.
145 EXPECT_FALSE(
146 dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
147 }
148 }
149 };
150
TEST_F(RestrictedConfigE2ETest,RestrictedConfigNoReport)151 TEST_F(RestrictedConfigE2ETest, RestrictedConfigNoReport) {
152 StatsdConfig config = CreateConfigWithOneMetric();
153 config.set_restricted_metrics_delegate_package_name("delegate");
154 sendConfig(config);
155 int64_t configAddedTimeNs = getElapsedRealtimeNs();
156
157 for (auto& event : CreateLogEvents(configAddedTimeNs)) {
158 service->OnLogEvent(event.get());
159 }
160
161 vector<uint8_t> output;
162 ConfigKey configKey(kCallingUid, kConfigKey);
163 service->getData(kConfigKey, kCallingUid, &output);
164
165 EXPECT_TRUE(output.empty());
166 }
167
TEST_F(RestrictedConfigE2ETest,NonRestrictedConfigGetReport)168 TEST_F(RestrictedConfigE2ETest, NonRestrictedConfigGetReport) {
169 StatsdConfig config = CreateConfigWithOneMetric();
170 sendConfig(config);
171 int64_t configAddedTimeNs = getElapsedRealtimeNs();
172
173 for (auto& event : CreateLogEvents(configAddedTimeNs)) {
174 service->OnLogEvent(event.get());
175 }
176
177 ConfigMetricsReport report = getReports(service->mProcessor, /*timestamp=*/10);
178 EXPECT_EQ(report.metrics_size(), 1);
179 }
180
TEST_F(RestrictedConfigE2ETest,RestrictedShutdownFlushToRestrictedDB)181 TEST_F(RestrictedConfigE2ETest, RestrictedShutdownFlushToRestrictedDB) {
182 StatsdConfig config = CreateConfigWithOneMetric();
183 config.set_restricted_metrics_delegate_package_name("delegate");
184 sendConfig(config);
185 int64_t configAddedTimeNs = getElapsedRealtimeNs();
186 std::vector<std::unique_ptr<LogEvent>> logEvents = CreateLogEvents(configAddedTimeNs);
187 for (const auto& e : logEvents) {
188 service->OnLogEvent(e.get());
189 }
190
191 service->informDeviceShutdown();
192
193 // Should not be written to non-restricted storage.
194 EXPECT_FALSE(StorageManager::hasConfigMetricsReport(ConfigKey(kCallingUid, kConfigKey)));
195 verifyRestrictedData(logEvents.size());
196 }
197
TEST_F(RestrictedConfigE2ETest,NonRestrictedOnShutdownWriteDataToDisk)198 TEST_F(RestrictedConfigE2ETest, NonRestrictedOnShutdownWriteDataToDisk) {
199 StatsdConfig config = CreateConfigWithOneMetric();
200 sendConfig(config);
201 int64_t configAddedTimeNs = getElapsedRealtimeNs();
202 for (auto& event : CreateLogEvents(configAddedTimeNs)) {
203 service->OnLogEvent(event.get());
204 }
205
206 service->informDeviceShutdown();
207
208 EXPECT_TRUE(StorageManager::hasConfigMetricsReport(ConfigKey(kCallingUid, kConfigKey)));
209 }
210
TEST_F(RestrictedConfigE2ETest,RestrictedConfigOnTerminateFlushToRestrictedDB)211 TEST_F(RestrictedConfigE2ETest, RestrictedConfigOnTerminateFlushToRestrictedDB) {
212 StatsdConfig config = CreateConfigWithOneMetric();
213 config.set_restricted_metrics_delegate_package_name("delegate");
214 sendConfig(config);
215 int64_t configAddedTimeNs = getElapsedRealtimeNs();
216 std::vector<std::unique_ptr<LogEvent>> logEvents = CreateLogEvents(configAddedTimeNs);
217 for (auto& event : logEvents) {
218 service->OnLogEvent(event.get());
219 }
220
221 service->Terminate();
222
223 EXPECT_FALSE(StorageManager::hasConfigMetricsReport(ConfigKey(kCallingUid, kConfigKey)));
224 verifyRestrictedData(logEvents.size());
225 }
226
TEST_F(RestrictedConfigE2ETest,NonRestrictedConfigOnTerminateWriteDataToDisk)227 TEST_F(RestrictedConfigE2ETest, NonRestrictedConfigOnTerminateWriteDataToDisk) {
228 StatsdConfig config = CreateConfigWithOneMetric();
229 sendConfig(config);
230 int64_t configAddedTimeNs = getElapsedRealtimeNs();
231 for (auto& event : CreateLogEvents(configAddedTimeNs)) {
232 service->OnLogEvent(event.get());
233 }
234
235 service->Terminate();
236
237 EXPECT_TRUE(StorageManager::hasConfigMetricsReport(ConfigKey(kCallingUid, kConfigKey)));
238 }
239
TEST_F(RestrictedConfigE2ETest,RestrictedConfigOnUpdateWithMetricRemoval)240 TEST_F(RestrictedConfigE2ETest, RestrictedConfigOnUpdateWithMetricRemoval) {
241 StatsdConfig complexConfig = CreateConfigWithTwoMetrics();
242 complexConfig.set_restricted_metrics_delegate_package_name(delegatePackageName);
243 sendConfig(complexConfig);
244 int64_t configAddedTimeNs = getElapsedRealtimeNs();
245 std::vector<std::unique_ptr<LogEvent>> logEvents = CreateLogEvents(configAddedTimeNs);
246 for (auto& event : logEvents) {
247 service->OnLogEvent(event.get());
248 }
249
250 // Use query API to make sure data is flushed.
251 std::stringstream query;
252 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(metricId);
253 service->querySql(query.str(), /*minSqlClientVersion=*/0,
254 /*policyConfig=*/{}, mockStatsQueryCallback,
255 /*configKey=*/kConfigKey, /*configPackage=*/configPackageName,
256 /*callingUid=*/delegateUid);
257 EXPECT_EQ(error, "");
258 EXPECT_EQ(rowCountResult, logEvents.size());
259 verifyRestrictedData(logEvents.size(), anotherMetricId, true);
260
261 // Update config to have only one metric
262 StatsdConfig config = CreateConfigWithOneMetric();
263 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
264 sendConfig(config);
265
266 // Make sure metric data is deleted.
267 verifyRestrictedData(logEvents.size(), metricId, true);
268 verifyRestrictedData(logEvents.size(), anotherMetricId, false);
269 }
270
TEST_F(RestrictedConfigE2ETest,TestSendRestrictedMetricsChangedBroadcast)271 TEST_F(RestrictedConfigE2ETest, TestSendRestrictedMetricsChangedBroadcast) {
272 vector<int64_t> receivedMetricIds;
273 int receiveCount = 0;
274 shared_ptr<MockPendingIntentRef> pir = SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
275 EXPECT_CALL(*pir, sendRestrictedMetricsChangedBroadcast(_))
276 .Times(7)
277 .WillRepeatedly(Invoke([&receivedMetricIds, &receiveCount](const vector<int64_t>& ids) {
278 receiveCount++;
279 receivedMetricIds = ids;
280 return Status::ok();
281 }));
282
283 // Set the operation. No configs present so empty list is returned.
284 vector<int64_t> returnedMetricIds;
285 service->setRestrictedMetricsChangedOperation(kConfigKey, configPackageName, pir, delegateUid,
286 &returnedMetricIds);
287 EXPECT_EQ(receiveCount, 0);
288 EXPECT_THAT(returnedMetricIds, IsEmpty());
289
290 // Add restricted config. Should receive one metric
291 StatsdConfig config = CreateConfigWithOneMetric();
292 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
293 sendConfig(config);
294 EXPECT_EQ(receiveCount, 1);
295 EXPECT_THAT(receivedMetricIds, UnorderedElementsAre(metricId));
296
297 // Config update, should receive two metrics.
298 config = CreateConfigWithTwoMetrics();
299 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
300 sendConfig(config);
301 EXPECT_EQ(receiveCount, 2);
302 EXPECT_THAT(receivedMetricIds, UnorderedElementsAre(metricId, anotherMetricId));
303
304 // Make config unrestricted. Should receive empty list.
305 config.clear_restricted_metrics_delegate_package_name();
306 sendConfig(config);
307 EXPECT_EQ(receiveCount, 3);
308 EXPECT_THAT(receivedMetricIds, IsEmpty());
309
310 // Update the unrestricted config. Nothing should be sent.
311 config = CreateConfigWithOneMetric();
312 sendConfig(config);
313
314 // Update config and make it restricted. Should receive one metric.
315 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
316 sendConfig(config);
317 EXPECT_EQ(receiveCount, 4);
318 EXPECT_THAT(receivedMetricIds, UnorderedElementsAre(metricId));
319
320 // Send an invalid config. Should receive empty list.
321 auto invalidCountMetric = config.add_count_metric();
322 invalidCountMetric->set_what(0);
323 sendConfig(config);
324 EXPECT_EQ(receiveCount, 5);
325 EXPECT_THAT(receivedMetricIds, IsEmpty());
326
327 service->removeRestrictedMetricsChangedOperation(kConfigKey, configPackageName, delegateUid);
328
329 // Nothing should be sent since the operation is removed.
330 config = CreateConfigWithTwoMetrics();
331 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
332 sendConfig(config);
333
334 // Set the operation. Two metrics should be returned.
335 returnedMetricIds.clear();
336 service->setRestrictedMetricsChangedOperation(kConfigKey, configPackageName, pir, delegateUid,
337 &returnedMetricIds);
338 EXPECT_THAT(returnedMetricIds, UnorderedElementsAre(metricId, anotherMetricId));
339 EXPECT_EQ(receiveCount, 5);
340
341 // Config update, should receive two metrics.
342 config = CreateConfigWithOneMetric();
343 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
344 sendConfig(config);
345 EXPECT_EQ(receiveCount, 6);
346 EXPECT_THAT(receivedMetricIds, UnorderedElementsAre(metricId));
347
348 // Remove the config and verify an empty list is received
349 service->removeConfiguration(kConfigKey, kCallingUid);
350 EXPECT_EQ(receiveCount, 7);
351 EXPECT_THAT(receivedMetricIds, IsEmpty());
352
353 // Cleanup.
354 service->removeRestrictedMetricsChangedOperation(kConfigKey, configPackageName, delegateUid);
355 }
356
TEST_F(RestrictedConfigE2ETest,TestSendRestrictedMetricsChangedBroadcastMultipleListeners)357 TEST_F(RestrictedConfigE2ETest, TestSendRestrictedMetricsChangedBroadcastMultipleListeners) {
358 const string configPackageName2 = "com.test.config.package2";
359 const int32_t delegateUid2 = delegateUid + 1, delegateUid3 = delegateUid + 2;
360 service->informOnePackage(configPackageName2, kCallingUid, 0, "", "", {});
361 service->informOnePackage(delegatePackageName, delegateUid2, 0, "", "", {});
362 service->informOnePackage("not.a.good.package", delegateUid3, 0, "", "", {});
363
364 vector<int64_t> receivedMetricIds;
365 int receiveCount = 0;
366 shared_ptr<MockPendingIntentRef> pir = SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
367 EXPECT_CALL(*pir, sendRestrictedMetricsChangedBroadcast(_))
368 .Times(2)
369 .WillRepeatedly(Invoke([&receivedMetricIds, &receiveCount](const vector<int64_t>& ids) {
370 receiveCount++;
371 receivedMetricIds = ids;
372 return Status::ok();
373 }));
374
375 int receiveCount2 = 0;
376 vector<int64_t> receivedMetricIds2;
377 shared_ptr<MockPendingIntentRef> pir2 = SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
378 EXPECT_CALL(*pir2, sendRestrictedMetricsChangedBroadcast(_))
379 .Times(2)
380 .WillRepeatedly(
381 Invoke([&receivedMetricIds2, &receiveCount2](const vector<int64_t>& ids) {
382 receiveCount2++;
383 receivedMetricIds2 = ids;
384 return Status::ok();
385 }));
386
387 // This one should never be called.
388 shared_ptr<MockPendingIntentRef> pir3 = SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
389 EXPECT_CALL(*pir3, sendRestrictedMetricsChangedBroadcast(_)).Times(0);
390
391 // Set the operations. No configs present so empty list is returned.
392 vector<int64_t> returnedMetricIds;
393 service->setRestrictedMetricsChangedOperation(kConfigKey, configPackageName, pir, delegateUid,
394 &returnedMetricIds);
395 EXPECT_EQ(receiveCount, 0);
396 EXPECT_THAT(returnedMetricIds, IsEmpty());
397
398 vector<int64_t> returnedMetricIds2;
399 service->setRestrictedMetricsChangedOperation(kConfigKey, configPackageName2, pir2,
400 delegateUid2, &returnedMetricIds2);
401 EXPECT_EQ(receiveCount2, 0);
402 EXPECT_THAT(returnedMetricIds2, IsEmpty());
403
404 // Represents a package listening for changes but doesn't match the restricted package in the
405 // config.
406 vector<int64_t> returnedMetricIds3;
407 service->setRestrictedMetricsChangedOperation(kConfigKey, configPackageName, pir3, delegateUid3,
408 &returnedMetricIds3);
409 EXPECT_THAT(returnedMetricIds3, IsEmpty());
410
411 // Add restricted config. Should receive one metric on pir1 and 2.
412 StatsdConfig config = CreateConfigWithOneMetric();
413 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
414 sendConfig(config);
415 EXPECT_EQ(receiveCount, 1);
416 EXPECT_THAT(receivedMetricIds, UnorderedElementsAre(metricId));
417 EXPECT_EQ(receiveCount2, 1);
418 EXPECT_THAT(receivedMetricIds2, UnorderedElementsAre(metricId));
419
420 // Config update, should receive two metrics on pir1 and 2.
421 config = CreateConfigWithTwoMetrics();
422 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
423 sendConfig(config);
424 EXPECT_EQ(receiveCount, 2);
425 EXPECT_THAT(receivedMetricIds, UnorderedElementsAre(metricId, anotherMetricId));
426 EXPECT_EQ(receiveCount2, 2);
427 EXPECT_THAT(receivedMetricIds2, UnorderedElementsAre(metricId, anotherMetricId));
428
429 // Cleanup.
430 service->removeRestrictedMetricsChangedOperation(kConfigKey, configPackageName, delegateUid);
431 service->removeRestrictedMetricsChangedOperation(kConfigKey, configPackageName2, delegateUid2);
432 service->removeRestrictedMetricsChangedOperation(kConfigKey, configPackageName, delegateUid3);
433 }
434
TEST_F(RestrictedConfigE2ETest,TestSendRestrictedMetricsChangedBroadcastMultipleMatchedConfigs)435 TEST_F(RestrictedConfigE2ETest, TestSendRestrictedMetricsChangedBroadcastMultipleMatchedConfigs) {
436 const int32_t callingUid2 = kCallingUid + 1;
437 service->informOnePackage(configPackageName, callingUid2, 0, "", "", {});
438
439 // Add restricted config.
440 StatsdConfig config = CreateConfigWithOneMetric();
441 config.set_restricted_metrics_delegate_package_name(delegatePackageName);
442 sendConfig(config);
443
444 // Add a second config.
445 const int64_t metricId2 = 42;
446 config.mutable_event_metric(0)->set_id(42);
447 string str;
448 config.SerializeToString(&str);
449 std::vector<uint8_t> configAsVec(str.begin(), str.end());
450 service->addConfiguration(kConfigKey, configAsVec, callingUid2);
451
452 // Set the operation. Matches multiple configs so a union of metrics are returned.
453 shared_ptr<MockPendingIntentRef> pir = SharedRefBase::make<StrictMock<MockPendingIntentRef>>();
454 vector<int64_t> returnedMetricIds;
455 service->setRestrictedMetricsChangedOperation(kConfigKey, configPackageName, pir, delegateUid,
456 &returnedMetricIds);
457 EXPECT_THAT(returnedMetricIds, UnorderedElementsAre(metricId, metricId2));
458
459 // Cleanup.
460 service->removeRestrictedMetricsChangedOperation(kConfigKey, configPackageName, delegateUid);
461
462 ConfigKey cfgKey(callingUid2, kConfigKey);
463 service->removeConfiguration(kConfigKey, callingUid2);
464 service->mProcessor->onDumpReport(cfgKey, getElapsedRealtimeNs(),
465 false /* include_current_bucket*/, true /* erase_data */,
466 ADB_DUMP, NO_TIME_CONSTRAINTS, nullptr);
467 }
468 #else
469 GTEST_LOG_(INFO) << "This test does nothing.\n";
470 #endif
471
472 } // namespace statsd
473 } // namespace os
474 } // namespace android
475