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