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 <android-modules-utils/sdk_level.h>
16 #include <gtest/gtest.h>
17
18 #include <vector>
19
20 #include "android-base/stringprintf.h"
21 #include "flags/FlagProvider.h"
22 #include "src/StatsLogProcessor.h"
23 #include "src/state/StateTracker.h"
24 #include "src/stats_log_util.h"
25 #include "src/storage/StorageManager.h"
26 #include "src/utils/RestrictedPolicyManager.h"
27 #include "stats_annotations.h"
28 #include "tests/statsd_test_util.h"
29
30 namespace android {
31 namespace os {
32 namespace statsd {
33
34 using android::modules::sdklevel::IsAtLeastU;
35 using base::StringPrintf;
36
37 #ifdef __ANDROID__
38
39 namespace {
40 const int64_t oneMonthLater = getWallClockNs() + 31 * 24 * 3600 * NS_PER_SEC;
41 const int64_t configId = 12345;
42 const string delegate_package_name = "com.test.restricted.metrics.package";
43 const int32_t delegate_uid = 1005;
44 const string config_package_name = "com.test.config.package";
45 const int32_t config_app_uid = 123;
46 const ConfigKey configKey(config_app_uid, configId);
47 const int64_t eightDaysAgo = getWallClockNs() - 8 * 24 * 3600 * NS_PER_SEC;
48 const int64_t oneDayAgo = getWallClockNs() - 1 * 24 * 3600 * NS_PER_SEC;
49 } // anonymous namespace
50
51 // Setup for test fixture.
52 class RestrictedEventMetricE2eTest : public ::testing::Test {
53 protected:
54 shared_ptr<MockStatsQueryCallback> mockStatsQueryCallback;
55 vector<string> queryDataResult;
56 vector<string> columnNamesResult;
57 vector<int32_t> columnTypesResult;
58 int32_t rowCountResult = 0;
59 string error;
60 sp<UidMap> uidMap;
61 sp<StatsLogProcessor> processor;
62 int32_t atomTag;
63 int64_t restrictedMetricId;
64 int64_t configAddedTimeNs;
65 StatsdConfig config;
66
67 private:
SetUp()68 void SetUp() override {
69 if (!IsAtLeastU()) {
70 GTEST_SKIP();
71 }
72
73 mockStatsQueryCallback = SharedRefBase::make<StrictMock<MockStatsQueryCallback>>();
74 EXPECT_CALL(*mockStatsQueryCallback, sendResults(_, _, _, _))
75 .Times(AnyNumber())
76 .WillRepeatedly(Invoke(
77 [this](const vector<string>& queryData, const vector<string>& columnNames,
78 const vector<int32_t>& columnTypes, int32_t rowCount) {
79 queryDataResult = queryData;
80 columnNamesResult = columnNames;
81 columnTypesResult = columnTypes;
82 rowCountResult = rowCount;
83 error = "";
84 return Status::ok();
85 }));
86 EXPECT_CALL(*mockStatsQueryCallback, sendFailure(_))
87 .Times(AnyNumber())
88 .WillRepeatedly(Invoke([this](const string& err) {
89 error = err;
90 queryDataResult.clear();
91 columnNamesResult.clear();
92 columnTypesResult.clear();
93 rowCountResult = 0;
94 return Status::ok();
95 }));
96
97 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
98
99 atomTag = 999;
100 AtomMatcher restrictedAtomMatcher = CreateSimpleAtomMatcher("restricted_matcher", atomTag);
101 *config.add_atom_matcher() = restrictedAtomMatcher;
102
103 EventMetric restrictedEventMetric =
104 createEventMetric("RestrictedMetricLogged", restrictedAtomMatcher.id(), nullopt);
105 *config.add_event_metric() = restrictedEventMetric;
106 restrictedMetricId = restrictedEventMetric.id();
107
108 config.set_restricted_metrics_delegate_package_name(delegate_package_name.c_str());
109
110 const int64_t baseTimeNs = 0; // 0:00
111 configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
112
113 uidMap = new UidMap();
114 uidMap->updateApp(configAddedTimeNs, String16(delegate_package_name.c_str()),
115 /*uid=*/delegate_uid, /*versionCode=*/1,
116 /*versionString=*/String16("v2"),
117 /*installer=*/String16(""), /*certificateHash=*/{});
118 uidMap->updateApp(configAddedTimeNs + 1, String16(config_package_name.c_str()),
119 /*uid=*/config_app_uid, /*versionCode=*/1,
120 /*versionString=*/String16("v2"),
121 /*installer=*/String16(""), /*certificateHash=*/{});
122
123 processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, configKey,
124 /*puller=*/nullptr, /*atomTag=*/0, uidMap);
125 }
126
TearDown()127 void TearDown() override {
128 Mock::VerifyAndClear(mockStatsQueryCallback.get());
129 queryDataResult.clear();
130 columnNamesResult.clear();
131 columnTypesResult.clear();
132 rowCountResult = 0;
133 error = "";
134 dbutils::deleteDb(configKey);
135 dbutils::deleteDb(ConfigKey(config_app_uid + 1, configId));
136 FlagProvider::getInstance().resetOverrides();
137 }
138 };
139
TEST_F(RestrictedEventMetricE2eTest,TestQueryThreeEvents)140 TEST_F(RestrictedEventMetricE2eTest, TestQueryThreeEvents) {
141 std::vector<std::unique_ptr<LogEvent>> events;
142
143 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
144 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 200));
145 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 300));
146
147 // Send log events to StatsLogProcessor.
148 for (auto& event : events) {
149 processor->OnLogEvent(event.get());
150 }
151
152 std::stringstream query;
153 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
154 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
155 /*policyConfig=*/{}, mockStatsQueryCallback,
156 /*configKey=*/configId, /*configPackage=*/config_package_name,
157 /*callingUid=*/delegate_uid);
158
159 EXPECT_EQ(rowCountResult, 3);
160 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
161 _, // wallClockNs
162 _, // field_1
163 to_string(atomTag), to_string(configAddedTimeNs + 200),
164 _, // wallClockNs
165 _, // field_1
166 to_string(atomTag), to_string(configAddedTimeNs + 300),
167 _, // wallClockNs
168 _ // field_1
169 ));
170
171 EXPECT_THAT(columnNamesResult,
172 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
173
174 EXPECT_THAT(columnTypesResult,
175 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
176 }
177
TEST_F(RestrictedEventMetricE2eTest,TestInvalidSchemaIncreasingFieldCount)178 TEST_F(RestrictedEventMetricE2eTest, TestInvalidSchemaIncreasingFieldCount) {
179 std::vector<std::unique_ptr<LogEvent>> events;
180
181 AStatsEvent* statsEvent = AStatsEvent_obtain();
182 AStatsEvent_setAtomId(statsEvent, atomTag);
183 AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY,
184 ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC);
185 AStatsEvent_overwriteTimestamp(statsEvent, configAddedTimeNs + 200);
186 // This event has two extra fields
187 AStatsEvent_writeString(statsEvent, "111");
188 AStatsEvent_writeInt32(statsEvent, 11);
189 AStatsEvent_writeFloat(statsEvent, 11.0);
190 std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
191 parseStatsEventToLogEvent(statsEvent, logEvent.get());
192
193 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
194 events.push_back(std::move(logEvent));
195
196 // Send log events to StatsLogProcessor.
197 for (auto& event : events) {
198 processor->OnLogEvent(event.get());
199 processor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST,
200 event->GetElapsedTimestampNs() + 20 * NS_PER_SEC,
201 getWallClockNs());
202 }
203
204 std::stringstream query;
205 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
206 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
207 /*policyConfig=*/{}, mockStatsQueryCallback,
208 /*configKey=*/configId, /*configPackage=*/config_package_name,
209 /*callingUid=*/delegate_uid);
210
211 EXPECT_EQ(rowCountResult, 1);
212 // Event 2 rejected.
213 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
214 _, // wallClockNs
215 _ // field_1
216 ));
217
218 EXPECT_THAT(columnNamesResult,
219 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
220
221 EXPECT_THAT(columnTypesResult,
222 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
223 }
224
TEST_F(RestrictedEventMetricE2eTest,TestInvalidSchemaDecreasingFieldCount)225 TEST_F(RestrictedEventMetricE2eTest, TestInvalidSchemaDecreasingFieldCount) {
226 std::vector<std::unique_ptr<LogEvent>> events;
227
228 AStatsEvent* statsEvent = AStatsEvent_obtain();
229 AStatsEvent_setAtomId(statsEvent, atomTag);
230 AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY,
231 ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC);
232 AStatsEvent_overwriteTimestamp(statsEvent, configAddedTimeNs + 100);
233 // This event has one extra field.
234 AStatsEvent_writeString(statsEvent, "111");
235 AStatsEvent_writeInt32(statsEvent, 11);
236 std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
237 parseStatsEventToLogEvent(statsEvent, logEvent.get());
238
239 events.push_back(std::move(logEvent));
240 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 200));
241
242 // Send log events to StatsLogProcessor.
243 for (auto& event : events) {
244 processor->OnLogEvent(event.get());
245 processor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST,
246 event->GetElapsedTimestampNs() + 20 * NS_PER_SEC,
247 getWallClockNs());
248 }
249
250 std::stringstream query;
251 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
252 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
253 /*policyConfig=*/{}, mockStatsQueryCallback,
254 /*configKey=*/configId, /*configPackage=*/config_package_name,
255 /*callingUid=*/delegate_uid);
256
257 EXPECT_EQ(rowCountResult, 1);
258 // Event 2 Rejected
259 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
260 _, // wallClockNs
261 "111", // field_1
262 to_string(11) // field_2
263 ));
264
265 EXPECT_THAT(columnNamesResult, ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs",
266 "field_1", "field_2"));
267
268 EXPECT_THAT(columnTypesResult, ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER,
269 SQLITE_TEXT, SQLITE_INTEGER));
270 }
271
TEST_F(RestrictedEventMetricE2eTest,TestInvalidSchemaDifferentFieldType)272 TEST_F(RestrictedEventMetricE2eTest, TestInvalidSchemaDifferentFieldType) {
273 std::vector<std::unique_ptr<LogEvent>> events;
274
275 AStatsEvent* statsEvent = AStatsEvent_obtain();
276 AStatsEvent_setAtomId(statsEvent, atomTag);
277 AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY,
278 ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC);
279 AStatsEvent_overwriteTimestamp(statsEvent, configAddedTimeNs + 200);
280 // This event has a string instead of an int field
281 AStatsEvent_writeString(statsEvent, "test_string");
282 std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
283 parseStatsEventToLogEvent(statsEvent, logEvent.get());
284
285 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
286 events.push_back(std::move(logEvent));
287
288 // Send log events to StatsLogProcessor.
289 for (auto& event : events) {
290 processor->OnLogEvent(event.get());
291 processor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST,
292 event->GetElapsedTimestampNs() + 20 * NS_PER_SEC,
293 getWallClockNs());
294 }
295
296 std::stringstream query;
297 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
298 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
299 /*policyConfig=*/{}, mockStatsQueryCallback,
300 /*configKey=*/configId, /*configPackage=*/config_package_name,
301 /*callingUid=*/delegate_uid);
302
303 EXPECT_EQ(rowCountResult, 1);
304 // Event 2 rejected.
305 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
306 _, // wallClockNs
307 _ // field_1
308 ));
309 EXPECT_THAT(columnNamesResult,
310 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
311 EXPECT_THAT(columnTypesResult,
312 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
313 }
314
TEST_F(RestrictedEventMetricE2eTest,TestNewMetricSchemaAcrossReboot)315 TEST_F(RestrictedEventMetricE2eTest, TestNewMetricSchemaAcrossReboot) {
316 int64_t currentWallTimeNs = getWallClockNs();
317 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
318 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
319 processor->OnLogEvent(event1.get());
320
321 std::stringstream query;
322 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
323 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
324 /*policyConfig=*/{}, mockStatsQueryCallback,
325 /*configKey=*/configId, /*configPackage=*/config_package_name,
326 /*callingUid=*/delegate_uid);
327 EXPECT_EQ(rowCountResult, 1);
328 EXPECT_THAT(queryDataResult,
329 ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime),
330 _, // wallTimestampNs
331 _ // field_1
332 ));
333 EXPECT_THAT(columnNamesResult,
334 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
335 EXPECT_THAT(columnTypesResult,
336 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
337
338 // Create a new processor to simulate a reboot
339 auto processor2 =
340 CreateStatsLogProcessor(/*baseTimeNs=*/0, configAddedTimeNs, config, configKey,
341 /*puller=*/nullptr, /*atomTag=*/0, uidMap);
342
343 // Create a restricted event with one extra field.
344 AStatsEvent* statsEvent = AStatsEvent_obtain();
345 AStatsEvent_setAtomId(statsEvent, atomTag);
346 AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY,
347 ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC);
348 AStatsEvent_overwriteTimestamp(statsEvent, originalEventElapsedTime + 100);
349 // This event has one extra field.
350 AStatsEvent_writeString(statsEvent, "111");
351 AStatsEvent_writeInt32(statsEvent, 11);
352 std::unique_ptr<LogEvent> event2 = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
353 parseStatsEventToLogEvent(statsEvent, event2.get());
354 processor2->OnLogEvent(event2.get());
355
356 processor2->querySql(query.str(), /*minSqlClientVersion=*/0,
357 /*policyConfig=*/{}, mockStatsQueryCallback,
358 /*configKey=*/configId, /*configPackage=*/config_package_name,
359 /*callingUid=*/delegate_uid);
360 EXPECT_EQ(rowCountResult, 1);
361 EXPECT_THAT(queryDataResult,
362 ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime + 100),
363 _, // wallTimestampNs
364 to_string(111), // field_1
365 to_string(11) // field_2
366 ));
367 EXPECT_THAT(columnNamesResult, ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs",
368 "field_1", "field_2"));
369 EXPECT_THAT(columnTypesResult, ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER,
370 SQLITE_TEXT, SQLITE_INTEGER));
371 }
372
TEST_F(RestrictedEventMetricE2eTest,TestOneEventMultipleUids)373 TEST_F(RestrictedEventMetricE2eTest, TestOneEventMultipleUids) {
374 uidMap->updateApp(configAddedTimeNs, String16(delegate_package_name.c_str()),
375 /*uid=*/delegate_uid + 1, /*versionCode=*/1,
376 /*versionString=*/String16("v2"),
377 /*installer=*/String16(""), /*certificateHash=*/{});
378 uidMap->updateApp(configAddedTimeNs + 1, String16(config_package_name.c_str()),
379 /*uid=*/config_app_uid + 1, /*versionCode=*/1,
380 /*versionString=*/String16("v2"),
381 /*installer=*/String16(""), /*certificateHash=*/{});
382
383 std::vector<std::unique_ptr<LogEvent>> events;
384
385 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
386
387 // Send log events to StatsLogProcessor.
388 for (auto& event : events) {
389 processor->OnLogEvent(event.get());
390 }
391
392 std::stringstream query;
393 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
394 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
395 /*policyConfig=*/{}, mockStatsQueryCallback,
396 /*configKey=*/configId, /*configPackage=*/config_package_name,
397 /*callingUid=*/delegate_uid);
398
399 EXPECT_EQ(rowCountResult, 1);
400 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
401 _, // wallClockNs
402 _ // field_1
403 ));
404 }
405
TEST_F(RestrictedEventMetricE2eTest,TestOneEventStaticUid)406 TEST_F(RestrictedEventMetricE2eTest, TestOneEventStaticUid) {
407 ConfigKey key2(2000, configId); // shell uid
408 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, key2, config);
409
410 std::vector<std::unique_ptr<LogEvent>> events;
411
412 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
413
414 // Send log events to StatsLogProcessor.
415 for (auto& event : events) {
416 processor->OnLogEvent(event.get());
417 }
418
419 std::stringstream query;
420 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
421 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
422 /*policyConfig=*/{}, mockStatsQueryCallback,
423 /*configKey=*/configId, /*configPackage=*/"AID_SHELL",
424 /*callingUid=*/delegate_uid);
425
426 EXPECT_EQ(rowCountResult, 1);
427 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
428 _, // wallClockNs
429 _ // field_1
430 ));
431 dbutils::deleteDb(key2);
432 }
433
TEST_F(RestrictedEventMetricE2eTest,TestTooManyConfigsAmbiguousQuery)434 TEST_F(RestrictedEventMetricE2eTest, TestTooManyConfigsAmbiguousQuery) {
435 ConfigKey key2(config_app_uid + 1, configId);
436 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, key2, config);
437
438 uidMap->updateApp(configAddedTimeNs, String16(delegate_package_name.c_str()),
439 /*uid=*/delegate_uid + 1, /*versionCode=*/1,
440 /*versionString=*/String16("v2"),
441 /*installer=*/String16(""), /*certificateHash=*/{});
442 uidMap->updateApp(configAddedTimeNs + 1, String16(config_package_name.c_str()),
443 /*uid=*/config_app_uid + 1, /*versionCode=*/1,
444 /*versionString=*/String16("v2"),
445 /*installer=*/String16(""), /*certificateHash=*/{});
446
447 std::vector<std::unique_ptr<LogEvent>> events;
448
449 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
450
451 // Send log events to StatsLogProcessor.
452 for (auto& event : events) {
453 processor->OnLogEvent(event.get());
454 }
455
456 std::stringstream query;
457 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
458 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
459 /*policyConfig=*/{}, mockStatsQueryCallback,
460 /*configKey=*/configId, /*configPackage=*/config_package_name,
461 /*callingUid=*/delegate_uid);
462
463 EXPECT_EQ(error, "Ambiguous ConfigKey");
464 dbutils::deleteDb(key2);
465 }
466
TEST_F(RestrictedEventMetricE2eTest,TestUnknownConfigPackage)467 TEST_F(RestrictedEventMetricE2eTest, TestUnknownConfigPackage) {
468 std::vector<std::unique_ptr<LogEvent>> events;
469
470 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
471
472 // Send log events to StatsLogProcessor.
473 for (auto& event : events) {
474 processor->OnLogEvent(event.get());
475 }
476
477 std::stringstream query;
478 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
479 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
480 /*policyConfig=*/{}, mockStatsQueryCallback,
481 /*configKey=*/configId, /*configPackage=*/"unknown.config.package",
482 /*callingUid=*/delegate_uid);
483
484 EXPECT_EQ(error, "No configs found matching the config key");
485 }
486
TEST_F(RestrictedEventMetricE2eTest,TestUnknownDelegatePackage)487 TEST_F(RestrictedEventMetricE2eTest, TestUnknownDelegatePackage) {
488 std::vector<std::unique_ptr<LogEvent>> events;
489
490 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
491
492 // Send log events to StatsLogProcessor.
493 for (auto& event : events) {
494 processor->OnLogEvent(event.get());
495 }
496
497 std::stringstream query;
498 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
499 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
500 /*policyConfig=*/{}, mockStatsQueryCallback,
501 /*configKey=*/configId, /*configPackage=*/config_package_name,
502 /*callingUid=*/delegate_uid + 1);
503
504 EXPECT_EQ(error, "No matching configs for restricted metrics delegate");
505 }
506
TEST_F(RestrictedEventMetricE2eTest,TestUnsupportedDatabaseVersion)507 TEST_F(RestrictedEventMetricE2eTest, TestUnsupportedDatabaseVersion) {
508 std::stringstream query;
509 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
510 processor->querySql(query.str(), /*minSqlClientVersion=*/INT_MAX,
511 /*policyConfig=*/{}, mockStatsQueryCallback,
512 /*configKey=*/configId, /*configPackage=*/config_package_name,
513 /*callingUid=*/delegate_uid);
514
515 EXPECT_THAT(error, StartsWith("Unsupported sqlite version"));
516 }
517
TEST_F(RestrictedEventMetricE2eTest,TestInvalidQuery)518 TEST_F(RestrictedEventMetricE2eTest, TestInvalidQuery) {
519 std::vector<std::unique_ptr<LogEvent>> events;
520
521 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
522
523 // Send log events to StatsLogProcessor.
524 for (auto& event : events) {
525 processor->OnLogEvent(event.get());
526 }
527
528 std::stringstream query;
529 query << "SELECT * FROM invalid_metric_" << dbutils::reformatMetricId(restrictedMetricId);
530 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
531 /*policyConfig=*/{}, mockStatsQueryCallback,
532 /*configKey=*/configId, /*configPackage=*/config_package_name,
533 /*callingUid=*/delegate_uid);
534
535 EXPECT_THAT(error, StartsWith("failed to query db"));
536 }
537
TEST_F(RestrictedEventMetricE2eTest,TestEnforceTtlRemovesOldEvents)538 TEST_F(RestrictedEventMetricE2eTest, TestEnforceTtlRemovesOldEvents) {
539 int64_t currentWallTimeNs = getWallClockNs();
540 // 8 days are used here because the TTL threshold is 7 days.
541 int64_t eightDaysAgo = currentWallTimeNs - 8 * 24 * 3600 * NS_PER_SEC;
542 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
543 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
544 event1->setLogdWallClockTimestampNs(eightDaysAgo);
545
546 // Send log events to StatsLogProcessor.
547 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
548 processor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST, originalEventElapsedTime + 20 * NS_PER_SEC,
549 getWallClockNs());
550 processor->EnforceDataTtls(currentWallTimeNs, originalEventElapsedTime + 100);
551
552 std::stringstream query;
553 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
554 string err;
555 std::vector<int32_t> columnTypes;
556 std::vector<string> columnNames;
557 std::vector<std::vector<std::string>> rows;
558 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
559 ASSERT_EQ(rows.size(), 0);
560 }
561
TEST_F(RestrictedEventMetricE2eTest,TestConfigRemovalDeletesData)562 TEST_F(RestrictedEventMetricE2eTest, TestConfigRemovalDeletesData) {
563 std::vector<std::unique_ptr<LogEvent>> events;
564
565 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
566
567 // Send log events to StatsLogProcessor.
568 for (auto& event : events) {
569 processor->OnLogEvent(event.get());
570 }
571 // Query to make sure data is flushed
572 std::stringstream query;
573 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
574 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
575 /*policyConfig=*/{}, mockStatsQueryCallback,
576 /*configKey=*/configId, /*configPackage=*/config_package_name,
577 /*callingUid=*/delegate_uid);
578
579 processor->OnConfigRemoved(configKey);
580
581 string err;
582 std::vector<int32_t> columnTypes;
583 std::vector<string> columnNames;
584 std::vector<std::vector<std::string>> rows;
585 EXPECT_FALSE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
586
587 EXPECT_THAT(err, StartsWith("unable to open database file"));
588 }
589
TEST_F(RestrictedEventMetricE2eTest,TestConfigRemovalDeletesDataWithoutFlush)590 TEST_F(RestrictedEventMetricE2eTest, TestConfigRemovalDeletesDataWithoutFlush) {
591 std::vector<std::unique_ptr<LogEvent>> events;
592
593 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
594
595 // Send log events to StatsLogProcessor.
596 for (auto& event : events) {
597 processor->OnLogEvent(event.get());
598 }
599 processor->OnConfigRemoved(configKey);
600
601 std::stringstream query;
602 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
603 string err;
604 std::vector<int32_t> columnTypes;
605 std::vector<string> columnNames;
606 std::vector<std::vector<std::string>> rows;
607 EXPECT_FALSE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
608
609 EXPECT_THAT(err, StartsWith("unable to open database file"));
610 }
611
TEST_F(RestrictedEventMetricE2eTest,TestConfigUpdateRestrictedDelegateCleared)612 TEST_F(RestrictedEventMetricE2eTest, TestConfigUpdateRestrictedDelegateCleared) {
613 std::vector<std::unique_ptr<LogEvent>> events;
614 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
615
616 // Send log events to StatsLogProcessor.
617 for (auto& event : events) {
618 processor->OnLogEvent(event.get());
619 }
620
621 // Update the existing config with no delegate
622 config.clear_restricted_metrics_delegate_package_name();
623 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config);
624
625 std::stringstream query;
626 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
627 string err;
628 std::vector<int32_t> columnTypes;
629 std::vector<string> columnNames;
630 std::vector<std::vector<std::string>> rows;
631 EXPECT_FALSE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
632 EXPECT_EQ(rows.size(), 0);
633 EXPECT_THAT(err, StartsWith("unable to open database file"));
634 dbutils::deleteDb(configKey);
635 }
636
TEST_F(RestrictedEventMetricE2eTest,TestNonModularConfigUpdateRestrictedDelegate)637 TEST_F(RestrictedEventMetricE2eTest, TestNonModularConfigUpdateRestrictedDelegate) {
638 std::vector<std::unique_ptr<LogEvent>> events;
639 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
640
641 // Send log events to StatsLogProcessor.
642 for (auto& event : events) {
643 processor->OnLogEvent(event.get());
644 }
645
646 // Update the existing config without modular update
647 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config, false);
648
649 std::stringstream query;
650 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
651 string err;
652 std::vector<int32_t> columnTypes;
653 std::vector<string> columnNames;
654 std::vector<std::vector<std::string>> rows;
655 EXPECT_FALSE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
656 EXPECT_EQ(rows.size(), 0);
657 EXPECT_THAT(err, StartsWith("no such table"));
658 dbutils::deleteDb(configKey);
659 }
660
TEST_F(RestrictedEventMetricE2eTest,TestModularConfigUpdateNewRestrictedDelegate)661 TEST_F(RestrictedEventMetricE2eTest, TestModularConfigUpdateNewRestrictedDelegate) {
662 config.clear_restricted_metrics_delegate_package_name();
663 // Update the existing config without a restricted delegate
664 processor->OnConfigUpdated(configAddedTimeNs + 10, configKey, config);
665
666 // Update the existing config with a new restricted delegate
667 config.set_restricted_metrics_delegate_package_name("new.delegate.package");
668 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config);
669
670 std::vector<std::unique_ptr<LogEvent>> events;
671 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 2 * NS_PER_SEC));
672
673 // Send log events to StatsLogProcessor.
674 for (auto& event : events) {
675 processor->OnLogEvent(event.get());
676 }
677
678 uint64_t dumpTimeNs = configAddedTimeNs + 100 * NS_PER_SEC;
679 ConfigMetricsReportList reports;
680 vector<uint8_t> buffer;
681 processor->onDumpReport(configKey, dumpTimeNs, true, true, ADB_DUMP, FAST, &buffer);
682 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
683 ASSERT_EQ(reports.reports_size(), 0);
684
685 // Assert the config update was not modular and a RestrictedEventMetricProducer was created.
686 std::stringstream query;
687 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
688 string err;
689 std::vector<int32_t> columnTypes;
690 std::vector<string> columnNames;
691 std::vector<std::vector<std::string>> rows;
692 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
693 EXPECT_EQ(rows.size(), 1);
694 EXPECT_THAT(rows[0],
695 ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 2 * NS_PER_SEC),
696 _, // wallClockNs
697 _ // field_1
698 ));
699 EXPECT_THAT(columnNames,
700 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
701 EXPECT_THAT(columnTypes,
702 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
703 }
704
TEST_F(RestrictedEventMetricE2eTest,TestModularConfigUpdateChangeRestrictedDelegate)705 TEST_F(RestrictedEventMetricE2eTest, TestModularConfigUpdateChangeRestrictedDelegate) {
706 std::vector<std::unique_ptr<LogEvent>> events;
707 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
708
709 // Send log events to StatsLogProcessor.
710 for (auto& event : events) {
711 processor->OnLogEvent(event.get());
712 }
713
714 // Update the existing config with a new restricted delegate
715 int32_t newDelegateUid = delegate_uid + 1;
716 config.set_restricted_metrics_delegate_package_name("new.delegate.package");
717 uidMap->updateApp(configAddedTimeNs, String16("new.delegate.package"),
718 /*uid=*/newDelegateUid, /*versionCode=*/1,
719 /*versionString=*/String16("v2"),
720 /*installer=*/String16(""), /*certificateHash=*/{});
721 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config);
722
723 std::stringstream query;
724 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
725 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
726 /*policyConfig=*/{}, mockStatsQueryCallback,
727 /*configKey=*/configId, /*configPackage=*/config_package_name,
728 /*callingUid=*/newDelegateUid);
729
730 EXPECT_EQ(rowCountResult, 1);
731 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(configAddedTimeNs + 100),
732 _, // wallClockNs
733 _ // field_1
734 ));
735 EXPECT_THAT(columnNamesResult,
736 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
737 EXPECT_THAT(columnTypesResult,
738 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
739 }
740
TEST_F(RestrictedEventMetricE2eTest,TestInvalidConfigUpdateRestrictedDelegate)741 TEST_F(RestrictedEventMetricE2eTest, TestInvalidConfigUpdateRestrictedDelegate) {
742 std::vector<std::unique_ptr<LogEvent>> events;
743 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
744
745 // Send log events to StatsLogProcessor.
746 for (auto& event : events) {
747 processor->OnLogEvent(event.get());
748 }
749
750 EventMetric metricWithoutMatcher = createEventMetric("metricWithoutMatcher", 999999, nullopt);
751 *config.add_event_metric() = metricWithoutMatcher;
752 // Update the existing config with an invalid config update
753 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config);
754
755 std::stringstream query;
756 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
757 string err;
758 std::vector<int32_t> columnTypes;
759 std::vector<string> columnNames;
760 std::vector<std::vector<std::string>> rows;
761 EXPECT_FALSE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
762 EXPECT_EQ(rows.size(), 0);
763 EXPECT_THAT(err, StartsWith("unable to open database file"));
764 }
765
TEST_F(RestrictedEventMetricE2eTest,TestRestrictedConfigUpdateDoesNotUpdateUidMap)766 TEST_F(RestrictedEventMetricE2eTest, TestRestrictedConfigUpdateDoesNotUpdateUidMap) {
767 auto& configKeyMap = processor->getUidMap()->mLastUpdatePerConfigKey;
768 EXPECT_EQ(configKeyMap.find(configKey), configKeyMap.end());
769 }
770
TEST_F(RestrictedEventMetricE2eTest,TestRestrictedConfigUpdateAddsDelegateRemovesUidMapEntry)771 TEST_F(RestrictedEventMetricE2eTest, TestRestrictedConfigUpdateAddsDelegateRemovesUidMapEntry) {
772 auto& configKeyMap = processor->getUidMap()->mLastUpdatePerConfigKey;
773 config.clear_restricted_metrics_delegate_package_name();
774 // Update the existing config without a restricted delegate
775 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config);
776 EXPECT_NE(configKeyMap.find(configKey), configKeyMap.end());
777 // Update the existing config with a new restricted delegate
778 config.set_restricted_metrics_delegate_package_name(delegate_package_name.c_str());
779 processor->OnConfigUpdated(configAddedTimeNs + 1 * NS_PER_SEC, configKey, config);
780 EXPECT_EQ(configKeyMap.find(configKey), configKeyMap.end());
781 }
782
TEST_F(RestrictedEventMetricE2eTest,TestLogEventsEnforceTtls)783 TEST_F(RestrictedEventMetricE2eTest, TestLogEventsEnforceTtls) {
784 int64_t currentWallTimeNs = getWallClockNs();
785 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
786 // 2 hours used here because the TTL check period is 1 hour.
787 int64_t newEventElapsedTime = configAddedTimeNs + 2 * 3600 * NS_PER_SEC + 1; // 2 hrs later
788 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
789 event1->setLogdWallClockTimestampNs(eightDaysAgo);
790 std::unique_ptr<LogEvent> event2 =
791 CreateRestrictedLogEvent(atomTag, originalEventElapsedTime + 100);
792 event2->setLogdWallClockTimestampNs(oneDayAgo);
793 std::unique_ptr<LogEvent> event3 = CreateRestrictedLogEvent(atomTag, newEventElapsedTime);
794 event3->setLogdWallClockTimestampNs(currentWallTimeNs);
795
796 processor->mLastTtlTime = originalEventElapsedTime;
797 // Send log events to StatsLogProcessor.
798 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
799 processor->OnLogEvent(event2.get(), newEventElapsedTime);
800 processor->OnLogEvent(event3.get(), newEventElapsedTime + 100);
801 processor->flushRestrictedDataLocked(newEventElapsedTime);
802
803 std::stringstream query;
804 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
805 string err;
806 std::vector<int32_t> columnTypes;
807 std::vector<string> columnNames;
808 std::vector<std::vector<std::string>> rows;
809 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
810 ASSERT_EQ(rows.size(), 2);
811 EXPECT_THAT(columnNames,
812 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
813 EXPECT_THAT(columnTypes,
814 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
815 EXPECT_THAT(rows[0], ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime + 100),
816 to_string(oneDayAgo), _));
817 EXPECT_THAT(rows[1], ElementsAre(to_string(atomTag), to_string(newEventElapsedTime),
818 to_string(currentWallTimeNs), _));
819 }
820
TEST_F(RestrictedEventMetricE2eTest,TestLogEventsDoesNotEnforceTtls)821 TEST_F(RestrictedEventMetricE2eTest, TestLogEventsDoesNotEnforceTtls) {
822 int64_t currentWallTimeNs = getWallClockNs();
823 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
824 // 30 min used here because the TTL check period is 1 hour.
825 int64_t newEventElapsedTime = configAddedTimeNs + (3600 * NS_PER_SEC) / 2; // 30 min later
826 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
827 event1->setLogdWallClockTimestampNs(eightDaysAgo);
828 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(atomTag, newEventElapsedTime);
829 event2->setLogdWallClockTimestampNs(currentWallTimeNs);
830
831 processor->mLastTtlTime = originalEventElapsedTime;
832 // Send log events to StatsLogProcessor.
833 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
834 processor->OnLogEvent(event2.get(), newEventElapsedTime);
835 processor->flushRestrictedDataLocked(newEventElapsedTime);
836
837 std::stringstream query;
838 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
839 string err;
840 std::vector<int32_t> columnTypes;
841 std::vector<string> columnNames;
842 std::vector<std::vector<std::string>> rows;
843 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
844 ASSERT_EQ(rows.size(), 2);
845 EXPECT_THAT(columnNames,
846 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
847 EXPECT_THAT(columnTypes,
848 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
849 EXPECT_THAT(rows[0], ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime),
850 to_string(eightDaysAgo), _));
851 EXPECT_THAT(rows[1], ElementsAre(to_string(atomTag), to_string(newEventElapsedTime),
852 to_string(currentWallTimeNs), _));
853 }
854
TEST_F(RestrictedEventMetricE2eTest,TestQueryEnforceTtls)855 TEST_F(RestrictedEventMetricE2eTest, TestQueryEnforceTtls) {
856 int64_t currentWallTimeNs = getWallClockNs();
857 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
858 // 30 min used here because the TTL check period is 1 hour.
859 int64_t newEventElapsedTime = configAddedTimeNs + (3600 * NS_PER_SEC) / 2; // 30 min later
860 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
861 event1->setLogdWallClockTimestampNs(eightDaysAgo);
862 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(atomTag, newEventElapsedTime);
863 event2->setLogdWallClockTimestampNs(currentWallTimeNs);
864
865 processor->mLastTtlTime = originalEventElapsedTime;
866 // Send log events to StatsLogProcessor.
867 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
868 processor->OnLogEvent(event2.get(), newEventElapsedTime);
869
870 std::stringstream query;
871 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
872 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
873 /*policyConfig=*/{}, mockStatsQueryCallback,
874 /*configKey=*/configId, /*configPackage=*/config_package_name,
875 /*callingUid=*/delegate_uid);
876
877 EXPECT_EQ(rowCountResult, 1);
878 EXPECT_THAT(queryDataResult, ElementsAre(to_string(atomTag), to_string(newEventElapsedTime),
879 to_string(currentWallTimeNs),
880 _ // field_1
881 ));
882 EXPECT_THAT(columnNamesResult,
883 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
884 EXPECT_THAT(columnTypesResult,
885 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
886 }
887
TEST_F(RestrictedEventMetricE2eTest,TestNotFlushed)888 TEST_F(RestrictedEventMetricE2eTest, TestNotFlushed) {
889 std::vector<std::unique_ptr<LogEvent>> events;
890 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
891 // Send log events to StatsLogProcessor.
892 for (auto& event : events) {
893 processor->OnLogEvent(event.get(), event->GetElapsedTimestampNs());
894 }
895 std::stringstream query;
896 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
897 string err;
898 std::vector<int32_t> columnTypes;
899 std::vector<string> columnNames;
900 std::vector<std::vector<std::string>> rows;
901 EXPECT_FALSE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
902 EXPECT_EQ(rows.size(), 0);
903 }
904
TEST_F(RestrictedEventMetricE2eTest,TestEnforceDbGuardrails)905 TEST_F(RestrictedEventMetricE2eTest, TestEnforceDbGuardrails) {
906 int64_t currentWallTimeNs = getWallClockNs();
907 int64_t originalEventElapsedTime =
908 configAddedTimeNs + (3600 * NS_PER_SEC) * 2; // 2 hours after boot
909 // 2 hours used here because the TTL check period is 1 hour.
910 int64_t dbEnforcementTimeNs =
911 configAddedTimeNs + (3600 * NS_PER_SEC) * 4; // 4 hours after boot
912 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
913 event1->setLogdWallClockTimestampNs(currentWallTimeNs);
914 // Send log events to StatsLogProcessor.
915 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
916
917 EXPECT_TRUE(StorageManager::hasFile(
918 base::StringPrintf("%s/%s", STATS_RESTRICTED_DATA_DIR, "123_12345.db").c_str()));
919 std::stringstream query;
920 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
921 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
922 /*policyConfig=*/{}, mockStatsQueryCallback,
923 /*configKey=*/configId, /*configPackage=*/config_package_name,
924 /*callingUid=*/delegate_uid);
925 EXPECT_EQ(rowCountResult, 1);
926 EXPECT_THAT(queryDataResult,
927 ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime),
928 to_string(currentWallTimeNs),
929 _ // field_1
930 ));
931 EXPECT_THAT(columnNamesResult,
932 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
933 EXPECT_THAT(columnTypesResult,
934 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
935
936 processor->enforceDbGuardrailsIfNecessaryLocked(oneMonthLater, dbEnforcementTimeNs);
937
938 EXPECT_FALSE(StorageManager::hasFile(
939 base::StringPrintf("%s/%s", STATS_RESTRICTED_DATA_DIR, "123_12345.db").c_str()));
940 }
941
TEST_F(RestrictedEventMetricE2eTest,TestEnforceDbGuardrailsDoesNotDeleteBeforeGuardrail)942 TEST_F(RestrictedEventMetricE2eTest, TestEnforceDbGuardrailsDoesNotDeleteBeforeGuardrail) {
943 int64_t currentWallTimeNs = getWallClockNs();
944 int64_t originalEventElapsedTime =
945 configAddedTimeNs + (3600 * NS_PER_SEC) * 2; // 2 hours after boot
946 // 2 hours used here because the TTL check period is 1 hour.
947 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
948 event1->setLogdWallClockTimestampNs(currentWallTimeNs);
949 // Send log events to StatsLogProcessor.
950 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
951
952 EXPECT_TRUE(StorageManager::hasFile(
953 base::StringPrintf("%s/%s", STATS_RESTRICTED_DATA_DIR, "123_12345.db").c_str()));
954 std::stringstream query;
955 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
956 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
957 /*policyConfig=*/{}, mockStatsQueryCallback,
958 /*configKey=*/configId, /*configPackage=*/config_package_name,
959 /*callingUid=*/delegate_uid);
960 EXPECT_EQ(rowCountResult, 1);
961 EXPECT_THAT(queryDataResult,
962 ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime),
963 to_string(currentWallTimeNs),
964 _ // field_1
965 ));
966 EXPECT_THAT(columnNamesResult,
967 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
968 EXPECT_THAT(columnTypesResult,
969 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
970
971 processor->enforceDbGuardrailsIfNecessaryLocked(oneMonthLater, originalEventElapsedTime);
972
973 EXPECT_TRUE(StorageManager::hasFile(
974 base::StringPrintf("%s/%s", STATS_RESTRICTED_DATA_DIR, "123_12345.db").c_str()));
975 }
976
TEST_F(RestrictedEventMetricE2eTest,TestFlushInWriteDataToDisk)977 TEST_F(RestrictedEventMetricE2eTest, TestFlushInWriteDataToDisk) {
978 std::vector<std::unique_ptr<LogEvent>> events;
979 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
980 // Send log events to StatsLogProcessor.
981 for (auto& event : events) {
982 processor->OnLogEvent(event.get(), event->GetElapsedTimestampNs());
983 }
984
985 // Call WriteDataToDisk after 20 second because cooldown period is 15 second.
986 processor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST, 20 * NS_PER_SEC, getWallClockNs());
987
988 std::stringstream query;
989 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
990 string err;
991 std::vector<int32_t> columnTypes;
992 std::vector<string> columnNames;
993 std::vector<std::vector<std::string>> rows;
994 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
995 EXPECT_EQ(rows.size(), 1);
996 }
997
TEST_F(RestrictedEventMetricE2eTest,TestFlushPeriodically)998 TEST_F(RestrictedEventMetricE2eTest, TestFlushPeriodically) {
999 std::vector<std::unique_ptr<LogEvent>> events;
1000
1001 events.push_back(CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100));
1002 events.push_back(CreateRestrictedLogEvent(
1003 atomTag, configAddedTimeNs + StatsdStats::kMinFlushRestrictedPeriodNs + 1));
1004
1005 // Send log events to StatsLogProcessor.
1006 for (auto& event : events) {
1007 processor->OnLogEvent(event.get(), event->GetElapsedTimestampNs());
1008 }
1009
1010 std::stringstream query;
1011 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
1012 string err;
1013 std::vector<int32_t> columnTypes;
1014 std::vector<string> columnNames;
1015 std::vector<std::vector<std::string>> rows;
1016 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
1017 // Only first event is flushed when second event is logged.
1018 EXPECT_EQ(rows.size(), 1);
1019 }
1020
TEST_F(RestrictedEventMetricE2eTest,TestOnLogEventMalformedDbNameDeleted)1021 TEST_F(RestrictedEventMetricE2eTest, TestOnLogEventMalformedDbNameDeleted) {
1022 vector<string> emptyData;
1023 string fileName = StringPrintf("%s/malformedname.db", STATS_RESTRICTED_DATA_DIR);
1024 StorageManager::writeFile(fileName.c_str(), emptyData.data(), emptyData.size());
1025 EXPECT_TRUE(StorageManager::hasFile(fileName.c_str()));
1026 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
1027 // 2 hours used here because the TTL check period is 1 hour.
1028 int64_t newEventElapsedTime = configAddedTimeNs + 2 * 3600 * NS_PER_SEC + 1; // 2 hrs later
1029 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(atomTag, newEventElapsedTime);
1030 event2->setLogdWallClockTimestampNs(getWallClockNs());
1031
1032 processor->mLastTtlTime = originalEventElapsedTime;
1033 // Send log events to StatsLogProcessor.
1034 processor->OnLogEvent(event2.get(), newEventElapsedTime);
1035
1036 EXPECT_FALSE(StorageManager::hasFile(fileName.c_str()));
1037 StorageManager::deleteFile(fileName.c_str());
1038 }
1039
TEST_F(RestrictedEventMetricE2eTest,TestRestrictedMetricSavesTtlToDisk)1040 TEST_F(RestrictedEventMetricE2eTest, TestRestrictedMetricSavesTtlToDisk) {
1041 metadata::StatsMetadataList result;
1042 processor->WriteMetadataToProto(getWallClockNs(), configAddedTimeNs, &result);
1043
1044 ASSERT_EQ(result.stats_metadata_size(), 1);
1045 metadata::StatsMetadata statsMetadata = result.stats_metadata(0);
1046 EXPECT_EQ(statsMetadata.config_key().config_id(), configId);
1047 EXPECT_EQ(statsMetadata.config_key().uid(), config_app_uid);
1048
1049 ASSERT_EQ(statsMetadata.metric_metadata_size(), 1);
1050 metadata::MetricMetadata metricMetadata = statsMetadata.metric_metadata(0);
1051 EXPECT_EQ(metricMetadata.metric_id(), restrictedMetricId);
1052 EXPECT_EQ(metricMetadata.restricted_category(), CATEGORY_UNKNOWN);
1053 result.Clear();
1054
1055 std::unique_ptr<LogEvent> event = CreateRestrictedLogEvent(atomTag, configAddedTimeNs + 100);
1056 processor->OnLogEvent(event.get());
1057 processor->WriteMetadataToProto(getWallClockNs(), configAddedTimeNs, &result);
1058
1059 ASSERT_EQ(result.stats_metadata_size(), 1);
1060 statsMetadata = result.stats_metadata(0);
1061 EXPECT_EQ(statsMetadata.config_key().config_id(), configId);
1062 EXPECT_EQ(statsMetadata.config_key().uid(), config_app_uid);
1063
1064 ASSERT_EQ(statsMetadata.metric_metadata_size(), 1);
1065 metricMetadata = statsMetadata.metric_metadata(0);
1066 EXPECT_EQ(metricMetadata.metric_id(), restrictedMetricId);
1067 EXPECT_EQ(metricMetadata.restricted_category(), CATEGORY_DIAGNOSTIC);
1068 }
1069
TEST_F(RestrictedEventMetricE2eTest,TestRestrictedMetricLoadsTtlFromDisk)1070 TEST_F(RestrictedEventMetricE2eTest, TestRestrictedMetricLoadsTtlFromDisk) {
1071 int64_t currentWallTimeNs = getWallClockNs();
1072 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
1073 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(atomTag, originalEventElapsedTime);
1074 event1->setLogdWallClockTimestampNs(eightDaysAgo);
1075 processor->OnLogEvent(event1.get(), originalEventElapsedTime);
1076 processor->flushRestrictedDataLocked(originalEventElapsedTime);
1077 int64_t wallClockNs = 1584991200 * NS_PER_SEC; // random time
1078 int64_t metadataWriteTime = originalEventElapsedTime + 5000 * NS_PER_SEC;
1079 processor->SaveMetadataToDisk(wallClockNs, metadataWriteTime);
1080
1081 std::stringstream query;
1082 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
1083 string err;
1084 std::vector<int32_t> columnTypes;
1085 std::vector<string> columnNames;
1086 std::vector<std::vector<std::string>> rows;
1087 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
1088 ASSERT_EQ(rows.size(), 1);
1089 EXPECT_THAT(columnNames,
1090 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
1091 EXPECT_THAT(columnTypes,
1092 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
1093 EXPECT_THAT(rows[0], ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime),
1094 to_string(eightDaysAgo), _));
1095
1096 auto processor2 =
1097 CreateStatsLogProcessor(/*baseTimeNs=*/0, configAddedTimeNs, config, configKey,
1098 /*puller=*/nullptr, /*atomTag=*/0, uidMap);
1099 // 2 hours used here because the TTL check period is 1 hour.
1100 int64_t newEventElapsedTime = configAddedTimeNs + 2 * 3600 * NS_PER_SEC + 1; // 2 hrs later
1101 processor2->LoadMetadataFromDisk(wallClockNs, newEventElapsedTime);
1102
1103 // Log another event and check that the original TTL is maintained across reboot
1104 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(atomTag, newEventElapsedTime);
1105 event2->setLogdWallClockTimestampNs(currentWallTimeNs);
1106 processor2->OnLogEvent(event2.get(), newEventElapsedTime);
1107 processor2->flushRestrictedDataLocked(newEventElapsedTime);
1108
1109 columnTypes.clear();
1110 columnNames.clear();
1111 rows.clear();
1112 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
1113 ASSERT_EQ(rows.size(), 1);
1114 EXPECT_THAT(columnNames,
1115 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
1116 EXPECT_THAT(columnTypes,
1117 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
1118 EXPECT_THAT(rows[0], ElementsAre(to_string(atomTag), to_string(newEventElapsedTime),
1119 to_string(currentWallTimeNs), _));
1120 }
1121
TEST_F(RestrictedEventMetricE2eTest,TestNewRestrictionCategoryEventDeletesTable)1122 TEST_F(RestrictedEventMetricE2eTest, TestNewRestrictionCategoryEventDeletesTable) {
1123 int64_t currentWallTimeNs = getWallClockNs();
1124 int64_t originalEventElapsedTime = configAddedTimeNs + 100;
1125 std::unique_ptr<LogEvent> event1 =
1126 CreateNonRestrictedLogEvent(atomTag, originalEventElapsedTime);
1127 processor->OnLogEvent(event1.get());
1128
1129 std::stringstream query;
1130 query << "SELECT * FROM metric_" << dbutils::reformatMetricId(restrictedMetricId);
1131 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
1132 /*policyConfig=*/{}, mockStatsQueryCallback,
1133 /*configKey=*/configId, /*configPackage=*/config_package_name,
1134 /*callingUid=*/delegate_uid);
1135 EXPECT_EQ(rowCountResult, 1);
1136 EXPECT_THAT(queryDataResult,
1137 ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime),
1138 _, // wallTimestampNs
1139 _ // field_1
1140 ));
1141 EXPECT_THAT(columnNamesResult,
1142 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
1143 EXPECT_THAT(columnTypesResult,
1144 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
1145
1146 // Log a second event that will go into the cache
1147 std::unique_ptr<LogEvent> event2 =
1148 CreateNonRestrictedLogEvent(atomTag, originalEventElapsedTime + 100);
1149 processor->OnLogEvent(event2.get());
1150
1151 // Log a third event with a different category
1152 std::unique_ptr<LogEvent> event3 =
1153 CreateRestrictedLogEvent(atomTag, originalEventElapsedTime + 200);
1154 processor->OnLogEvent(event3.get());
1155
1156 processor->querySql(query.str(), /*minSqlClientVersion=*/0,
1157 /*policyConfig=*/{}, mockStatsQueryCallback,
1158 /*configKey=*/configId, /*configPackage=*/config_package_name,
1159 /*callingUid=*/delegate_uid);
1160 EXPECT_EQ(rowCountResult, 1);
1161 EXPECT_THAT(queryDataResult,
1162 ElementsAre(to_string(atomTag), to_string(originalEventElapsedTime + 200),
1163 _, // wallTimestampNs
1164 _ // field_1
1165 ));
1166 EXPECT_THAT(columnNamesResult,
1167 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
1168 EXPECT_THAT(columnTypesResult,
1169 ElementsAre(SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER, SQLITE_INTEGER));
1170 }
1171
TEST_F(RestrictedEventMetricE2eTest,TestDeviceInfoTableCreated)1172 TEST_F(RestrictedEventMetricE2eTest, TestDeviceInfoTableCreated) {
1173 std::string query = "SELECT * FROM device_info";
1174 processor->querySql(query.c_str(), /*minSqlClientVersion=*/0,
1175 /*policyConfig=*/{}, mockStatsQueryCallback,
1176 /*configKey=*/configId, /*configPackage=*/config_package_name,
1177 /*callingUid=*/delegate_uid);
1178 EXPECT_EQ(rowCountResult, 1);
1179 EXPECT_THAT(queryDataResult, ElementsAre(_, _, _, _, _, _, _, _, _, _));
1180 EXPECT_THAT(columnNamesResult,
1181 ElementsAre("sdkVersion", "model", "product", "hardware", "device", "osBuild",
1182 "fingerprint", "brand", "manufacturer", "board"));
1183 EXPECT_THAT(columnTypesResult,
1184 ElementsAre(SQLITE_INTEGER, SQLITE_TEXT, SQLITE_TEXT, SQLITE_TEXT, SQLITE_TEXT,
1185 SQLITE_TEXT, SQLITE_TEXT, SQLITE_TEXT, SQLITE_TEXT, SQLITE_TEXT));
1186 }
1187 #else
1188 GTEST_LOG_(INFO) << "This test does nothing.\n";
1189 #endif
1190
1191 } // namespace statsd
1192 } // namespace os
1193 } // namespace android
1194