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