1 // Copyright (C) 2017 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "packages/UidMap.h"
16
17 #include <android/util/ProtoOutputStream.h>
18 #include <gtest/gtest.h>
19 #include <private/android_filesystem_config.h>
20 #include <src/uid_data.pb.h>
21 #include <stdio.h>
22
23 #include "StatsLogProcessor.h"
24 #include "StatsService.h"
25 #include "config/ConfigKey.h"
26 #include "gtest_matchers.h"
27 #include "guardrail/StatsdStats.h"
28 #include "hash.h"
29 #include "logd/LogEvent.h"
30 #include "statsd_test_util.h"
31 #include "statslog_statsdtest.h"
32
33 using namespace android;
34
35 namespace android {
36 namespace os {
37 namespace statsd {
38
39 using aidl::android::util::StatsEventParcel;
40 using android::util::ProtoOutputStream;
41 using android::util::ProtoReader;
42 using ::ndk::SharedRefBase;
43 using Change = UidMapping_Change;
44
45 #ifdef __ANDROID__
46
47 namespace {
48 const string kApp1 = "app1.sharing.1";
49 const string kApp2 = "app2.sharing.1";
50 const string kApp3 = "app3";
51
52 const vector<int32_t> kUids{1000, 1000, 1500};
53 const vector<int64_t> kVersions{4, 5, 6};
54 const vector<string> kVersionStrings{"v1", "v1", "v2"};
55 const vector<string> kApps{kApp1, kApp2, kApp3};
56 const vector<string> kInstallers{"", "", "com.android.vending"};
57 const vector<vector<uint8_t>> kCertificateHashes{{'a', 'z'}, {'b', 'c'}, {'d', 'e'}};
58 const vector<uint8_t> kDeleted(3, false);
59
60 const UidMapOptions DEFAULT_OPTIONS = {.includeVersionStrings = true,
61 .includeInstaller = true,
62 .truncatedCertificateHashSize = 0,
63 .omitSystemUids = false};
64
createUidData(const vector<int32_t> & uids,const vector<int64_t> & versions,const vector<string> & versionStrings,const vector<string> & apps,const vector<string> & installers,const vector<vector<uint8_t>> & certificateHashes)65 UidData createUidData(const vector<int32_t>& uids, const vector<int64_t>& versions,
66 const vector<string>& versionStrings, const vector<string>& apps,
67 const vector<string>& installers,
68 const vector<vector<uint8_t>>& certificateHashes) {
69 // Populate UidData from app data.
70 UidData uidData;
71 for (size_t i = 0; i < uids.size(); i++) {
72 ApplicationInfo* appInfo = uidData.add_app_info();
73 appInfo->set_uid(uids[i]);
74 appInfo->set_version(versions[i]);
75 appInfo->set_version_string(versionStrings[i]);
76 appInfo->set_package_name(apps[i]);
77 appInfo->set_installer(installers[i]);
78 appInfo->set_certificate_hash(certificateHashes[i].data(), certificateHashes[i].size());
79 }
80 return uidData;
81 }
82
sendPackagesToStatsd(shared_ptr<StatsService> service,const vector<int32_t> & uids,const vector<int64_t> & versions,const vector<string> & versionStrings,const vector<string> & apps,const vector<string> & installers,const vector<vector<uint8_t>> & certificateHashes)83 void sendPackagesToStatsd(shared_ptr<StatsService> service, const vector<int32_t>& uids,
84 const vector<int64_t>& versions, const vector<string>& versionStrings,
85 const vector<string>& apps, const vector<string>& installers,
86 const vector<vector<uint8_t>>& certificateHashes) {
87 // Create file descriptor from serialized UidData.
88 // Create a file that lives in memory.
89 ScopedFileDescriptor scopedFd(memfd_create("doesn't matter", MFD_CLOEXEC));
90 const int fd = scopedFd.get();
91 int f = fcntl(fd, F_GETFD); // Read the file descriptor flags.
92 ASSERT_NE(-1, f); // Ensure there was no error while reading file descriptor flags.
93 ASSERT_TRUE(f & FD_CLOEXEC);
94
95 UidData uidData =
96 createUidData(uids, versions, versionStrings, apps, installers, certificateHashes);
97 ASSERT_TRUE(uidData.SerializeToFileDescriptor(fd));
98 ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
99
100 // Send file descriptor containing app data to statsd.
101 service->informAllUidData(scopedFd);
102 }
103
104 // Returns a vector of the same length as values param. Each i-th element in the returned vector is
105 // the index at which values[i] appears in the list denoted by the begin and end iterators.
106 template <typename Iterator, typename ValueType>
computeIndices(const Iterator begin,const Iterator end,const vector<ValueType> & values)107 vector<uint32_t> computeIndices(const Iterator begin, const Iterator end,
108 const vector<ValueType>& values) {
109 vector<uint32_t> indices;
110 for (const ValueType& value : values) {
111 Iterator it = find(begin, end, value);
112 indices.emplace_back(distance(begin, it));
113 }
114 return indices;
115 }
116
117 class UidMapTestAppendUidMapBase : public Test {
118 protected:
119 const ConfigKey cfgKey;
120 const sp<UidMap> uidMap;
121
UidMapTestAppendUidMapBase()122 UidMapTestAppendUidMapBase() : cfgKey(1, StringToId("config1")), uidMap(new UidMap()) {
123 }
124 };
125
126 } // anonymous namespace
127
TEST(UidMapTest,TestIsolatedUID)128 TEST(UidMapTest, TestIsolatedUID) {
129 sp<UidMap> m = new UidMap();
130 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
131 sp<AlarmMonitor> anomalyAlarmMonitor;
132 sp<AlarmMonitor> subscriberAlarmMonitor;
133 // Construct the processor with a no-op sendBroadcast function that does nothing.
134 StatsLogProcessor p(
135 m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
136 [](const ConfigKey& key) { return true; },
137 [](const int&, const vector<int64_t>&) { return true; },
138 [](const ConfigKey&, const string&, const vector<int64_t>&) {},
139 std::make_shared<LogEventFilter>());
140
141 std::unique_ptr<LogEvent> addEvent = CreateIsolatedUidChangedEvent(
142 1 /*timestamp*/, 100 /*hostUid*/, 101 /*isolatedUid*/, 1 /*is_create*/);
143 EXPECT_EQ(101, m->getHostUidOrSelf(101));
144 p.OnLogEvent(addEvent.get());
145 EXPECT_EQ(100, m->getHostUidOrSelf(101));
146
147 std::unique_ptr<LogEvent> removeEvent = CreateIsolatedUidChangedEvent(
148 1 /*timestamp*/, 100 /*hostUid*/, 101 /*isolatedUid*/, 0 /*is_create*/);
149 p.OnLogEvent(removeEvent.get());
150 EXPECT_EQ(101, m->getHostUidOrSelf(101));
151 }
152
TEST(UidMapTest,TestUpdateMap)153 TEST(UidMapTest, TestUpdateMap) {
154 const sp<UidMap> uidMap = new UidMap();
155 const shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(
156 uidMap, /* queue */ nullptr, std::make_shared<LogEventFilter>());
157 sendPackagesToStatsd(service, kUids, kVersions, kVersionStrings, kApps, kInstallers,
158 kCertificateHashes);
159
160 EXPECT_TRUE(uidMap->hasApp(1000, kApp1));
161 EXPECT_TRUE(uidMap->hasApp(1000, kApp2));
162 EXPECT_TRUE(uidMap->hasApp(1500, kApp3));
163 EXPECT_FALSE(uidMap->hasApp(1000, "not.app"));
164
165 std::set<string> name_set = uidMap->getAppNamesFromUid(1000u, true /* returnNormalized */);
166 EXPECT_THAT(name_set, UnorderedElementsAre(kApp1, kApp2));
167
168 name_set = uidMap->getAppNamesFromUid(1500u, true /* returnNormalized */);
169 EXPECT_THAT(name_set, UnorderedElementsAre(kApp3));
170
171 name_set = uidMap->getAppNamesFromUid(12345, true /* returnNormalized */);
172 EXPECT_THAT(name_set, IsEmpty());
173
174 vector<PackageInfo> expectedPackageInfos =
175 buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers,
176 kCertificateHashes, kDeleted, /* installerIndices */ {},
177 /* hashStrings */ false);
178
179 PackageInfoSnapshot packageInfoSnapshot = getPackageInfoSnapshot(uidMap);
180
181 EXPECT_THAT(packageInfoSnapshot.package_info(),
182 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
183 }
184
TEST(UidMapTest,TestUpdateMapMultiple)185 TEST(UidMapTest, TestUpdateMapMultiple) {
186 const sp<UidMap> uidMap = new UidMap();
187 const shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(
188 uidMap, /* queue */ nullptr, std::make_shared<LogEventFilter>());
189 sendPackagesToStatsd(service, kUids, kVersions, kVersionStrings, kApps, kInstallers,
190 kCertificateHashes);
191
192 // Remove kApp3, and add NewApp
193 vector<int32_t> uids(kUids);
194 uids.back() = 2000;
195 vector<string> apps(kApps);
196 apps.back() = "NewApp";
197 vector<string> installers(kInstallers);
198 installers.back() = "NewInstaller";
199
200 sendPackagesToStatsd(service, uids, kVersions, kVersionStrings, apps, installers,
201 kCertificateHashes);
202
203 EXPECT_TRUE(uidMap->hasApp(1000, kApp1));
204 EXPECT_TRUE(uidMap->hasApp(1000, kApp2));
205 EXPECT_TRUE(uidMap->hasApp(2000, "NewApp"));
206 EXPECT_FALSE(uidMap->hasApp(1500, kApp3));
207 EXPECT_FALSE(uidMap->hasApp(1000, "not.app"));
208
209 std::set<string> name_set = uidMap->getAppNamesFromUid(1000u, true /* returnNormalized */);
210 EXPECT_THAT(name_set, UnorderedElementsAre(kApp1, kApp2));
211
212 name_set = uidMap->getAppNamesFromUid(2000, true /* returnNormalized */);
213 EXPECT_THAT(name_set, UnorderedElementsAre("newapp"));
214
215 name_set = uidMap->getAppNamesFromUid(1500, true /* returnNormalized */);
216 EXPECT_THAT(name_set, IsEmpty());
217
218 vector<PackageInfo> expectedPackageInfos =
219 buildPackageInfos(apps, uids, kVersions, kVersionStrings, installers,
220 kCertificateHashes, kDeleted, /* installerIndices */ {},
221 /* hashStrings */ false);
222
223 PackageInfoSnapshot packageInfoSnapshot = getPackageInfoSnapshot(uidMap);
224
225 EXPECT_THAT(packageInfoSnapshot.package_info(),
226 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
227 }
228
TEST(UidMapTest,TestRemoveApp)229 TEST(UidMapTest, TestRemoveApp) {
230 const sp<UidMap> uidMap = new UidMap();
231 const shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(
232 uidMap, /* queue */ nullptr, std::make_shared<LogEventFilter>());
233 sendPackagesToStatsd(service, kUids, kVersions, kVersionStrings, kApps, kInstallers,
234 kCertificateHashes);
235
236 service->informOnePackageRemoved(kApp1, 1000);
237 EXPECT_FALSE(uidMap->hasApp(1000, kApp1));
238 EXPECT_TRUE(uidMap->hasApp(1000, kApp2));
239 EXPECT_TRUE(uidMap->hasApp(1500, kApp3));
240 std::set<string> name_set = uidMap->getAppNamesFromUid(1000, true /* returnNormalized */);
241 EXPECT_THAT(name_set, UnorderedElementsAre(kApp2));
242
243 vector<uint8_t> deleted(kDeleted);
244 deleted[0] = true;
245 vector<PackageInfo> expectedPackageInfos =
246 buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers,
247 kCertificateHashes, deleted, /* installerIndices */ {},
248 /* hashStrings */ false);
249 PackageInfoSnapshot packageInfoSnapshot = getPackageInfoSnapshot(uidMap);
250 EXPECT_THAT(packageInfoSnapshot.package_info(),
251 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
252
253 service->informOnePackageRemoved(kApp2, 1000);
254 EXPECT_FALSE(uidMap->hasApp(1000, kApp1));
255 EXPECT_FALSE(uidMap->hasApp(1000, kApp2));
256 EXPECT_TRUE(uidMap->hasApp(1500, kApp3));
257 EXPECT_FALSE(uidMap->hasApp(1000, "not.app"));
258 name_set = uidMap->getAppNamesFromUid(1000, true /* returnNormalized */);
259 EXPECT_THAT(name_set, IsEmpty());
260
261 deleted[1] = true;
262 expectedPackageInfos = buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers,
263 kCertificateHashes, deleted, /* installerIndices */ {},
264 /* hashStrings */ false);
265 packageInfoSnapshot = getPackageInfoSnapshot(uidMap);
266 EXPECT_THAT(packageInfoSnapshot.package_info(),
267 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
268
269 service->informOnePackageRemoved(kApp3, 1500);
270 EXPECT_FALSE(uidMap->hasApp(1000, kApp1));
271 EXPECT_FALSE(uidMap->hasApp(1000, kApp2));
272 EXPECT_FALSE(uidMap->hasApp(1500, kApp3));
273 EXPECT_FALSE(uidMap->hasApp(1000, "not.app"));
274 name_set = uidMap->getAppNamesFromUid(1500, true /* returnNormalized */);
275 EXPECT_THAT(name_set, IsEmpty());
276
277 deleted[2] = true;
278 expectedPackageInfos = buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers,
279 kCertificateHashes, deleted, /* installerIndices */ {},
280 /* hashStrings */ false);
281 packageInfoSnapshot = getPackageInfoSnapshot(uidMap);
282 EXPECT_THAT(packageInfoSnapshot.package_info(),
283 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
284 }
285
TEST(UidMapTest,TestUpdateApp)286 TEST(UidMapTest, TestUpdateApp) {
287 const sp<UidMap> uidMap = new UidMap();
288 const shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(
289 uidMap, /* queue */ nullptr, std::make_shared<LogEventFilter>());
290 sendPackagesToStatsd(service, kUids, kVersions, kVersionStrings, kApps, kInstallers,
291 kCertificateHashes);
292
293 // Update app1 version.
294 service->informOnePackage(kApps[0].c_str(), kUids[0], /* version */ 40,
295 /* versionString */ "v40", kInstallers[0], kCertificateHashes[0]);
296 EXPECT_THAT(uidMap->getAppVersion(kUids[0], kApps[0]), Eq(40));
297 std::set<string> name_set = uidMap->getAppNamesFromUid(1000, true /* returnNormalized */);
298 EXPECT_THAT(name_set, UnorderedElementsAre(kApp1, kApp2));
299
300 // Add a new name for uid 1000.
301 service->informOnePackage("NeW_aPP1_NAmE", 1000, /* version */ 40,
302 /* versionString */ "v40", /* installer */ "com.android.vending",
303 /* certificateHash */ {'a'});
304 name_set = uidMap->getAppNamesFromUid(1000, true /* returnNormalized */);
305 EXPECT_THAT(name_set, UnorderedElementsAre(kApp1, kApp2, "new_app1_name"));
306
307 // Re-add the same name for another uid 2000
308 service->informOnePackage("NeW_aPP1_NAmE", 2000, /* version */ 1,
309 /* versionString */ "v1", /* installer */ "",
310 /* certificateHash */ {'b'});
311 name_set = uidMap->getAppNamesFromUid(2000, true /* returnNormalized */);
312 EXPECT_THAT(name_set, UnorderedElementsAre("new_app1_name"));
313
314 // Re-add existing package with different installer
315 service->informOnePackage("NeW_aPP1_NAmE", 2000, /* version */ 1,
316 /* versionString */ "v1", /* installer */ "new_installer",
317 /* certificateHash */ {'b'});
318 name_set = uidMap->getAppNamesFromUid(2000, true /* returnNormalized */);
319 EXPECT_THAT(name_set, UnorderedElementsAre("new_app1_name"));
320
321 vector<int32_t> uids = concatenate(kUids, {1000, 2000});
322 vector<int64_t> versions = concatenate(kVersions, {40, 1});
323 versions[0] = 40;
324 vector<string> versionStrings = concatenate(kVersionStrings, {"v40", "v1"});
325 versionStrings[0] = "v40";
326 vector<string> apps = concatenate(kApps, {"NeW_aPP1_NAmE", "NeW_aPP1_NAmE"});
327 vector<string> installers = concatenate(kInstallers, {"com.android.vending", "new_installer"});
328 vector<uint8_t> deleted = concatenate(kDeleted, {false, false});
329 vector<vector<uint8_t>> certHashes = concatenate(kCertificateHashes, {{'a'}, {'b'}});
330 vector<PackageInfo> expectedPackageInfos =
331 buildPackageInfos(apps, uids, versions, versionStrings, installers, certHashes, deleted,
332 /* installerIndices */ {},
333 /* hashStrings */ false);
334
335 PackageInfoSnapshot packageInfoSnapshot = getPackageInfoSnapshot(uidMap);
336 EXPECT_THAT(packageInfoSnapshot.package_info(),
337 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
338 }
339
340 // Test that uid map returns at least one snapshot even if we already obtained
341 // this snapshot from a previous call to getData.
TEST(UidMapTest,TestOutputIncludesAtLeastOneSnapshot)342 TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot) {
343 UidMap m;
344 // Initialize single config key.
345 ConfigKey config1(1, StringToId("config1"));
346 m.OnConfigUpdated(config1);
347
348 UidData uidData;
349 *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1000, /*version*/ 5, "v1", kApp2);
350
351 m.updateMap(1 /* timestamp */, uidData);
352
353 // Set the last timestamp for this config key to be newer.
354 m.mLastUpdatePerConfigKey[config1] = 2;
355
356 ProtoOutputStream proto;
357 m.appendUidMap(/* timestamp */ 3, config1, DEFAULT_OPTIONS, /* str_set */ nullptr, &proto);
358
359 // Check there's still a uidmap attached this one.
360 UidMapping results;
361 outputStreamToProto(&proto, &results);
362 ASSERT_EQ(1, results.snapshots_size());
363 EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
364 }
365
TEST(UidMapTest,TestRemovedAppRetained)366 TEST(UidMapTest, TestRemovedAppRetained) {
367 UidMap m;
368 // Initialize single config key.
369 ConfigKey config1(1, StringToId("config1"));
370 m.OnConfigUpdated(config1);
371
372 UidData uidData;
373 *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1000, /*version*/ 5, "v5", kApp2);
374
375 m.updateMap(1 /* timestamp */, uidData);
376 m.removeApp(2, kApp2, 1000);
377
378 ProtoOutputStream proto;
379 m.appendUidMap(/* timestamp */ 3, config1, DEFAULT_OPTIONS,
380 /* str_set */ nullptr, &proto);
381
382 // Snapshot should still contain this item as deleted.
383 UidMapping results;
384 outputStreamToProto(&proto, &results);
385 ASSERT_EQ(1, results.snapshots(0).package_info_size());
386 EXPECT_EQ(true, results.snapshots(0).package_info(0).deleted());
387 }
388
TEST(UidMapTest,TestRemovedAppOverGuardrail)389 TEST(UidMapTest, TestRemovedAppOverGuardrail) {
390 UidMap m;
391 // Initialize single config key.
392 ConfigKey config1(1, StringToId("config1"));
393 m.OnConfigUpdated(config1);
394 const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
395
396 UidData uidData;
397 for (int j = 0; j < maxDeletedApps + 10; j++) {
398 *uidData.add_app_info() = createApplicationInfo(/*uid*/ j, /*version*/ j, "v", kApp1);
399 }
400 m.updateMap(1 /* timestamp */, uidData);
401
402 // First, verify that we have the expected number of items.
403 UidMapping results;
404 ProtoOutputStream proto;
405 m.appendUidMap(/* timestamp */ 3, config1, DEFAULT_OPTIONS,
406 /* str_set */ nullptr, &proto);
407 outputStreamToProto(&proto, &results);
408 ASSERT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
409
410 // Now remove all the apps.
411 m.updateMap(1 /* timestamp */, uidData);
412 for (int j = 0; j < maxDeletedApps + 10; j++) {
413 m.removeApp(4, kApp1, j);
414 }
415
416 proto.clear();
417 m.appendUidMap(/* timestamp */ 5, config1, DEFAULT_OPTIONS,
418 /* str_set */ nullptr, &proto);
419 // Snapshot drops the first nine items.
420 outputStreamToProto(&proto, &results);
421 ASSERT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
422 }
423
TEST(UidMapTest,TestClearingOutput)424 TEST(UidMapTest, TestClearingOutput) {
425 UidMap m;
426
427 ConfigKey config1(1, StringToId("config1"));
428 ConfigKey config2(1, StringToId("config2"));
429
430 m.OnConfigUpdated(config1);
431
432 UidData uidData;
433 *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1000, /*version*/ 4, "v4", kApp1);
434 *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1000, /*version*/ 5, "v5", kApp2);
435 m.updateMap(1 /* timestamp */, uidData);
436
437 ProtoOutputStream proto;
438 m.appendUidMap(/* timestamp */ 2, config1, DEFAULT_OPTIONS,
439 /* str_set */ nullptr, &proto);
440 UidMapping results;
441 outputStreamToProto(&proto, &results);
442 ASSERT_EQ(1, results.snapshots_size());
443
444 // We have to keep at least one snapshot in memory at all times.
445 proto.clear();
446 m.appendUidMap(/* timestamp */ 2, config1, DEFAULT_OPTIONS,
447 /* str_set */ nullptr, &proto);
448 outputStreamToProto(&proto, &results);
449 ASSERT_EQ(1, results.snapshots_size());
450
451 // Now add another configuration.
452 m.OnConfigUpdated(config2);
453 m.updateApp(5, kApp1, 1000, 40, "v40", "", /* certificateHash */ {});
454 ASSERT_EQ(1U, m.mChanges.size());
455 proto.clear();
456 m.appendUidMap(/* timestamp */ 6, config1, DEFAULT_OPTIONS,
457 /* str_set */ nullptr, &proto);
458 outputStreamToProto(&proto, &results);
459 ASSERT_EQ(1, results.snapshots_size());
460 ASSERT_EQ(1, results.changes_size());
461 ASSERT_EQ(1U, m.mChanges.size());
462
463 // Add another delta update.
464 m.updateApp(7, kApp2, 1001, 41, "v41", "", /* certificateHash */ {});
465 ASSERT_EQ(2U, m.mChanges.size());
466
467 // We still can't remove anything.
468 proto.clear();
469 m.appendUidMap(/* timestamp */ 8, config1, DEFAULT_OPTIONS,
470 /* str_set */ nullptr, &proto);
471 outputStreamToProto(&proto, &results);
472 ASSERT_EQ(1, results.snapshots_size());
473 ASSERT_EQ(1, results.changes_size());
474 ASSERT_EQ(2U, m.mChanges.size());
475
476 proto.clear();
477 m.appendUidMap(/* timestamp */ 9, config2, DEFAULT_OPTIONS,
478 /* str_set */ nullptr, &proto);
479 outputStreamToProto(&proto, &results);
480 ASSERT_EQ(1, results.snapshots_size());
481 ASSERT_EQ(2, results.changes_size());
482 // At this point both should be cleared.
483 ASSERT_EQ(0U, m.mChanges.size());
484 }
485
TEST(UidMapTest,TestMemoryComputed)486 TEST(UidMapTest, TestMemoryComputed) {
487 UidMap m;
488
489 ConfigKey config1(1, StringToId("config1"));
490 m.OnConfigUpdated(config1);
491
492 size_t startBytes = m.mBytesUsed;
493 UidData uidData;
494 *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1000, /*version*/ 1, "v1", kApp1);
495 m.updateMap(1 /* timestamp */, uidData);
496
497 m.updateApp(3, kApp1, 1000, 40, "v40", "", /* certificateHash */ {});
498
499 ProtoOutputStream proto;
500 m.appendUidMap(/* timestamp */ 2, config1, DEFAULT_OPTIONS,
501 /* str_set */ nullptr, &proto);
502 size_t prevBytes = m.mBytesUsed;
503
504 m.appendUidMap(/* timestamp */ 4, config1, DEFAULT_OPTIONS,
505 /* str_set */ nullptr, &proto);
506 EXPECT_TRUE(m.mBytesUsed < prevBytes);
507 }
508
TEST(UidMapTest,TestMemoryGuardrail)509 TEST(UidMapTest, TestMemoryGuardrail) {
510 UidMap m;
511 string buf;
512
513 ConfigKey config1(1, StringToId("config1"));
514 m.OnConfigUpdated(config1);
515
516 size_t startBytes = m.mBytesUsed;
517 UidData uidData;
518 for (int i = 0; i < 100; i++) {
519 buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
520 *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", buf);
521 }
522 m.updateMap(1 /* timestamp */, uidData);
523
524 m.updateApp(3, "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0", 1000, 2, "v2", "",
525 /* certificateHash */ {});
526 ASSERT_EQ(1U, m.mChanges.size());
527
528 // Now force deletion by limiting the memory to hold one delta change.
529 m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
530 m.updateApp(5, "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0", 1000, 4, "v4", "",
531 /* certificateHash */ {});
532 ASSERT_EQ(1U, m.mChanges.size());
533 }
534
535 namespace {
536 class UidMapTestAppendUidMap : public UidMapTestAppendUidMapBase {
537 protected:
538 const shared_ptr<StatsService> service;
539
540 set<string> installersSet;
541 set<uint64_t> installerHashSet;
542 vector<uint64_t> installerHashes;
543
UidMapTestAppendUidMap()544 UidMapTestAppendUidMap()
545 : UidMapTestAppendUidMapBase(),
546 service(SharedRefBase::make<StatsService>(uidMap, /* queue */ nullptr,
547 std::make_shared<LogEventFilter>())) {
548 }
549
SetUp()550 void SetUp() override {
551 sendPackagesToStatsd(service, kUids, kVersions, kVersionStrings, kApps, kInstallers,
552 kCertificateHashes);
553
554 for (const string& installer : kInstallers) {
555 installersSet.insert(installer);
556 uint64_t installerHash = Hash64(installer);
557 installerHashes.emplace_back(installerHash);
558 installerHashSet.insert(installerHash);
559 }
560 }
561 };
562
TEST_F(UidMapTestAppendUidMap,TestInstallersInReportIncludeInstallerAndHashStrings)563 TEST_F(UidMapTestAppendUidMap, TestInstallersInReportIncludeInstallerAndHashStrings) {
564 ProtoOutputStream proto;
565 set<string> strSet;
566 uidMap->appendUidMap(/* timestamp */ 3, cfgKey, DEFAULT_OPTIONS, &strSet, &proto);
567
568 UidMapping results;
569 outputStreamToProto(&proto, &results);
570
571 // Verify hashes for all installers are in the installer_hash list.
572 EXPECT_THAT(results.installer_hash(), UnorderedElementsAreArray(installerHashSet));
573
574 EXPECT_THAT(results.installer_name(), IsEmpty());
575
576 // Verify all installer names are added to the strSet argument.
577 EXPECT_THAT(strSet, IsSupersetOf(installersSet));
578
579 ASSERT_THAT(results.snapshots_size(), Eq(1));
580
581 // Compute installer indices for each package.
582 // Find the location of each installerHash from the input in the results.
583 // installerIndices[i] is the index in results.installer_hash() that matches installerHashes[i].
584 vector<uint32_t> installerIndices = computeIndices(
585 results.installer_hash().begin(), results.installer_hash().end(), installerHashes);
586
587 vector<PackageInfo> expectedPackageInfos =
588 buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers,
589 /* certHashes */ {}, kDeleted, installerIndices,
590 /* hashStrings */ true);
591
592 EXPECT_THAT(strSet, IsSupersetOf(kApps));
593
594 EXPECT_THAT(results.snapshots(0).package_info(),
595 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
596 }
597
TEST_F(UidMapTestAppendUidMap,TestInstallersInReportIncludeInstallerAndDontHashStrings)598 TEST_F(UidMapTestAppendUidMap, TestInstallersInReportIncludeInstallerAndDontHashStrings) {
599 ProtoOutputStream proto;
600 uidMap->appendUidMap(/* timestamp */ 3, cfgKey, DEFAULT_OPTIONS,
601 /* str_set */ nullptr, &proto);
602
603 UidMapping results;
604 outputStreamToProto(&proto, &results);
605
606 // Verify all installers are in the installer_name list.
607 EXPECT_THAT(results.installer_name(), UnorderedElementsAreArray(installersSet));
608
609 EXPECT_THAT(results.installer_hash(), IsEmpty());
610
611 ASSERT_THAT(results.snapshots_size(), Eq(1));
612
613 vector<uint32_t> installerIndices = computeIndices(results.installer_name().begin(),
614 results.installer_name().end(), kInstallers);
615
616 vector<PackageInfo> expectedPackageInfos =
617 buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers,
618 /* certHashes */ {}, kDeleted, installerIndices,
619 /* hashStrings */ false);
620
621 EXPECT_THAT(results.snapshots(0).package_info(),
622 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
623 }
624
625 // Set up parameterized test with set<string>* parameter to control whether strings are hashed
626 // or not in the report. A value of nullptr indicates strings should not be hashed and non-null
627 // values indicates strings are hashed in the report and the original strings are added to this set.
628 class UidMapTestAppendUidMapHashStrings : public UidMapTestAppendUidMap,
629 public WithParamInterface<set<string>*> {
630 public:
631 inline static set<string> strSet;
632
633 protected:
SetUp()634 void SetUp() override {
635 strSet.clear();
636 }
637 };
638
639 INSTANTIATE_TEST_SUITE_P(
640 HashStrings, UidMapTestAppendUidMapHashStrings,
641 Values(nullptr, &(UidMapTestAppendUidMapHashStrings::strSet)),
__anon91e6dee10602(const TestParamInfo<UidMapTestAppendUidMapHashStrings::ParamType>& info) 642 [](const TestParamInfo<UidMapTestAppendUidMapHashStrings::ParamType>& info) {
643 return info.param == nullptr ? "NoHashStrings" : "HashStrings";
644 });
645
TEST_P(UidMapTestAppendUidMapHashStrings,TestNoIncludeInstallersInReport)646 TEST_P(UidMapTestAppendUidMapHashStrings, TestNoIncludeInstallersInReport) {
647 ProtoOutputStream proto;
648 UidMapOptions options = DEFAULT_OPTIONS;
649 options.includeInstaller = false;
650 uidMap->appendUidMap(/* timestamp */ 3, cfgKey, options,
651 /* str_set */ GetParam(), &proto);
652
653 UidMapping results;
654 outputStreamToProto(&proto, &results);
655
656 // Verify installer lists are empty.
657 EXPECT_THAT(results.installer_name(), IsEmpty());
658 EXPECT_THAT(results.installer_hash(), IsEmpty());
659
660 ASSERT_THAT(results.snapshots_size(), Eq(1));
661
662 // Verify that none of installer, installer_hash, installer_index fields in PackageInfo are
663 // populated.
664 EXPECT_THAT(results.snapshots(0).package_info(),
665 Each(Property(&PackageInfo::has_installer, IsFalse())));
666 EXPECT_THAT(results.snapshots(0).package_info(),
667 Each(Property(&PackageInfo::has_installer_hash, IsFalse())));
668 EXPECT_THAT(results.snapshots(0).package_info(),
669 Each(Property(&PackageInfo::has_installer_index, IsFalse())));
670 }
671
672 // Set up parameterized test for testing with different truncation hash sizes for the certificates.
673 class UidMapTestTruncateCertificateHash : public UidMapTestAppendUidMap,
674 public WithParamInterface<uint8_t> {};
675
676 INSTANTIATE_TEST_SUITE_P(ZeroOneTwoThree, UidMapTestTruncateCertificateHash,
677 Range(uint8_t{0}, uint8_t{4}));
678
TEST_P(UidMapTestTruncateCertificateHash,TestCertificateHashesTruncated)679 TEST_P(UidMapTestTruncateCertificateHash, TestCertificateHashesTruncated) {
680 const uint8_t hashSize = GetParam();
681 ProtoOutputStream proto;
682 UidMapOptions options = DEFAULT_OPTIONS;
683 options.includeInstaller = false;
684 options.truncatedCertificateHashSize = hashSize;
685 uidMap->appendUidMap(/* timestamp */ 3, cfgKey, options,
686 /* str_set */ nullptr, &proto);
687
688 UidMapping results;
689 outputStreamToProto(&proto, &results);
690
691 ASSERT_THAT(results.snapshots_size(), Eq(1));
692
693 vector<vector<uint8_t>> certHashes = kCertificateHashes;
694 for (vector<uint8_t>& certHash : certHashes) {
695 certHash.resize(certHash.size() < hashSize ? certHash.size() : hashSize);
696 }
697 vector<PackageInfo> expectedPackageInfos =
698 buildPackageInfos(kApps, kUids, kVersions, kVersionStrings,
699 /* installers */ {}, certHashes, kDeleted,
700 /* installerIndices*/ {},
701 /* hashStrings */ false);
702
703 EXPECT_THAT(results.snapshots(0).package_info(),
704 UnorderedPointwise(EqPackageInfo(), expectedPackageInfos));
705 }
706
707 class UidMapTestAppendUidMapSystemUsedUids : public UidMapTestAppendUidMapBase {
708 protected:
709 static const uint64_t bucketStartTimeNs = 10000000000; // 0:10
710 uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
711 StatsdConfig config;
712
SetUp()713 void SetUp() override {
714 UidData uidData =
715 createUidData({AID_LMKD, AID_APP_START + 1, AID_USER_OFFSET + AID_UWB,
716 AID_USER_OFFSET + AID_APP_START + 2, AID_ROOT, AID_APP_START - 1,
717 AID_APP_START} /* uids */,
718 {1, 2, 3, 4, 5, 6, 7} /* versions */,
719 {"v1", "v2", "v3", "v4", "v5", "v6", "v7"} /* versionStrings */,
720 {"LMKD", "app1", "UWB", "app2", "root", "app3", "app4"} /* apps */,
721 vector(7, string("installer")) /* installers */,
722 vector(7, vector<uint8_t>{}) /* certificateHashes */);
723
724 uidMap->updateMap(/* timestamp */ 1, uidData);
725
726 uidMap->updateApp(/* timestamp */ 5, "LMKD", AID_LMKD, /* versionCode */ 10, "v10",
727 /* installer */ "", /* certificateHash */ {});
728 uidMap->updateApp(/* timestamp */ 6, "UWB", AID_USER_OFFSET + AID_UWB, /* versionCode */ 20,
729 "v20", /* installer */ "", /* certificateHash */ {});
730 uidMap->updateApp(/* timestamp */ 7, "root", AID_ROOT, /* versionCode */ 50, "v50",
731 /* installer */ "", /* certificateHash */ {});
732 uidMap->updateApp(/* timestamp */ 8, "app3", AID_APP_START - 1, /* versionCode */ 60, "v60",
733 /* installer */ "", /* certificateHash */ {});
734 uidMap->updateApp(/* timestamp */ 9, "app4", AID_APP_START, /* versionCode */ 70, "v70",
735 /* installer */ "", /* certificateHash */ {});
736
737 *config.add_atom_matcher() =
738 CreateSimpleAtomMatcher("TestAtomMatcher", util::SYNC_STATE_CHANGED);
739 *config.add_event_metric() =
740 createEventMetric("TestAtomReported", config.atom_matcher(0).id(), nullopt);
741 }
742
createStatsLogProcessor(const StatsdConfig & config) const743 inline sp<StatsLogProcessor> createStatsLogProcessor(const StatsdConfig& config) const {
744 return CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey,
745 /* puller */ nullptr, /* puller atomTag */ 0, uidMap);
746 }
747
getUidMapping(const sp<StatsLogProcessor> & processor) const748 UidMapping getUidMapping(const sp<StatsLogProcessor>& processor) const {
749 vector<uint8_t> buffer;
750 processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
751 FAST, &buffer);
752 ConfigMetricsReportList reports;
753 reports.ParseFromArray(&buffer[0], buffer.size());
754 return reports.reports(0).uid_map();
755 }
756 };
757
TEST_F(UidMapTestAppendUidMapSystemUsedUids,testHasSystemAndUnusedUids)758 TEST_F(UidMapTestAppendUidMapSystemUsedUids, testHasSystemAndUnusedUids) {
759 sp<StatsLogProcessor> processor = createStatsLogProcessor(config);
760 UidMapping results = getUidMapping(processor);
761
762 ASSERT_EQ(results.snapshots_size(), 1);
763 EXPECT_THAT(
764 results.snapshots(0).package_info(),
765 UnorderedElementsAre(Property(&PackageInfo::uid, AID_LMKD),
766 Property(&PackageInfo::uid, AID_USER_OFFSET + AID_UWB),
767 Property(&PackageInfo::uid, AID_ROOT),
768 Property(&PackageInfo::uid, AID_APP_START - 1),
769 Property(&PackageInfo::uid, AID_APP_START),
770 Property(&PackageInfo::uid, AID_APP_START + 1),
771 Property(&PackageInfo::uid, AID_USER_OFFSET + AID_APP_START + 2)));
772
773 EXPECT_THAT(results.changes(),
774 UnorderedElementsAre(Property(&Change::uid, AID_LMKD),
775 Property(&Change::uid, AID_USER_OFFSET + AID_UWB),
776 Property(&Change::uid, AID_ROOT),
777 Property(&Change::uid, AID_APP_START - 1),
778 Property(&Change::uid, AID_APP_START)));
779 }
780
TEST_F(UidMapTestAppendUidMapSystemUsedUids,testHasNoSystemUids)781 TEST_F(UidMapTestAppendUidMapSystemUsedUids, testHasNoSystemUids) {
782 config.mutable_statsd_config_options()->set_omit_system_uids_in_uidmap(true);
783 sp<StatsLogProcessor> processor = createStatsLogProcessor(config);
784 UidMapping results = getUidMapping(processor);
785
786 ASSERT_EQ(results.snapshots_size(), 1);
787 EXPECT_THAT(results.snapshots(0).package_info(),
788 Each(Property(&PackageInfo::uid,
789 AllOf(Not(Eq(AID_LMKD)), Not(Eq(AID_USER_OFFSET + AID_UWB)),
790 Not(Eq(AID_ROOT)), Not(Eq(AID_APP_START - 1))))));
791
792 EXPECT_THAT(results.changes(), ElementsAre(Property(&Change::uid, AID_APP_START)));
793 }
794
TEST_F(UidMapTestAppendUidMapSystemUsedUids,testOmitSystemAndUnusedUidsEmpty)795 TEST_F(UidMapTestAppendUidMapSystemUsedUids, testOmitSystemAndUnusedUidsEmpty) {
796 config.mutable_statsd_config_options()->set_omit_system_uids_in_uidmap(true);
797 config.mutable_statsd_config_options()->set_omit_unused_uids_in_uidmap(true);
798
799 sp<StatsLogProcessor> processor = createStatsLogProcessor(config);
800 UidMapping results = getUidMapping(processor);
801
802 ASSERT_EQ(results.snapshots_size(), 1);
803 ASSERT_EQ(results.snapshots(0).package_info_size(), 0);
804 ASSERT_EQ(results.changes_size(), 0);
805 }
806
TEST_F(UidMapTestAppendUidMapSystemUsedUids,testOmitSystemAndUnusedUids)807 TEST_F(UidMapTestAppendUidMapSystemUsedUids, testOmitSystemAndUnusedUids) {
808 config.mutable_statsd_config_options()->set_omit_system_uids_in_uidmap(true);
809 config.mutable_statsd_config_options()->set_omit_unused_uids_in_uidmap(true);
810
811 sp<StatsLogProcessor> processor = createStatsLogProcessor(config);
812
813 auto event = CreateSyncStartEvent(bucketStartTimeNs + 1, {AID_LMKD, AID_APP_START + 1},
814 {"tag", "tag"}, "sync_name");
815 processor->OnLogEvent(event.get());
816
817 UidMapping results = getUidMapping(processor);
818
819 ASSERT_EQ(results.snapshots_size(), 1);
820 EXPECT_THAT(results.snapshots(0).package_info(),
821 UnorderedElementsAre(Property(&PackageInfo::uid, AID_APP_START + 1)));
822 ASSERT_EQ(results.changes_size(), 0);
823 }
824
TEST_F(UidMapTestAppendUidMapSystemUsedUids,testOmitSystemAndUnusedUidsEmptyWithAllowlist)825 TEST_F(UidMapTestAppendUidMapSystemUsedUids, testOmitSystemAndUnusedUidsEmptyWithAllowlist) {
826 config.mutable_statsd_config_options()->set_omit_system_uids_in_uidmap(true);
827 config.mutable_statsd_config_options()->set_omit_unused_uids_in_uidmap(true);
828 config.mutable_statsd_config_options()->add_uidmap_package_allowlist("LMKD");
829 config.mutable_statsd_config_options()->add_uidmap_package_allowlist("app4");
830
831 sp<StatsLogProcessor> processor = createStatsLogProcessor(config);
832 UidMapping results = getUidMapping(processor);
833
834 ASSERT_EQ(results.snapshots_size(), 1);
835 EXPECT_THAT(results.snapshots(0).package_info(),
836 UnorderedElementsAre(Property(&PackageInfo::uid, AID_LMKD),
837 Property(&PackageInfo::uid, AID_APP_START)));
838 EXPECT_THAT(results.changes(), UnorderedElementsAre(Property(&Change::uid, AID_LMKD),
839 Property(&Change::uid, AID_APP_START)));
840 }
841
TEST_F(UidMapTestAppendUidMapSystemUsedUids,testOmitSystemAndUnusedUidsWithAllowlist)842 TEST_F(UidMapTestAppendUidMapSystemUsedUids, testOmitSystemAndUnusedUidsWithAllowlist) {
843 config.mutable_statsd_config_options()->set_omit_system_uids_in_uidmap(true);
844 config.mutable_statsd_config_options()->set_omit_unused_uids_in_uidmap(true);
845 config.mutable_statsd_config_options()->add_uidmap_package_allowlist("LMKD");
846 config.mutable_statsd_config_options()->add_uidmap_package_allowlist("app1");
847
848 sp<StatsLogProcessor> processor = createStatsLogProcessor(config);
849 auto event = CreateSyncStartEvent(bucketStartTimeNs + 1, {AID_ROOT, AID_LMKD, AID_APP_START},
850 {"tag", "tag", "tag"}, "sync_name");
851 processor->OnLogEvent(event.get());
852 UidMapping results = getUidMapping(processor);
853
854 ASSERT_EQ(results.snapshots_size(), 1);
855 EXPECT_THAT(results.snapshots(0).package_info(),
856 UnorderedElementsAre(Property(&PackageInfo::uid, AID_LMKD),
857 Property(&PackageInfo::uid, AID_APP_START),
858 Property(&PackageInfo::uid, AID_APP_START + 1)));
859 EXPECT_THAT(results.changes(), UnorderedElementsAre(Property(&Change::uid, AID_LMKD),
860 Property(&Change::uid, AID_APP_START)));
861 }
862
TEST(UidMapTest,TestUsedUidsE2e)863 TEST(UidMapTest, TestUsedUidsE2e) {
864 const int ATOM_1 = 1, ATOM_2 = 2, ATOM_3 = 3, ATOM_4 = 4, ATOM_5 = 10001, ATOM_6 = 6;
865 StatsdConfig config;
866 config.mutable_statsd_config_options()->set_omit_unused_uids_in_uidmap(true);
867 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
868 AtomMatcher eventMatcher = CreateSimpleAtomMatcher("M1", ATOM_1);
869 *config.add_atom_matcher() = eventMatcher;
870 AtomMatcher countMatcher = CreateSimpleAtomMatcher("M2", ATOM_2);
871 *config.add_atom_matcher() = countMatcher;
872 AtomMatcher durationStartMatcher = CreateSimpleAtomMatcher("M3_START", ATOM_3);
873 auto fvmStart = durationStartMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
874 fvmStart->set_field(2); // State field.
875 fvmStart->set_eq_int(0);
876 *config.add_atom_matcher() = durationStartMatcher;
877 AtomMatcher durationStopMatcher = CreateSimpleAtomMatcher("M3_STOP", ATOM_3);
878 auto fvmStop = durationStopMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
879 fvmStop->set_field(2);
880 fvmStop->set_eq_int(1);
881 *config.add_atom_matcher() = durationStopMatcher;
882 AtomMatcher gaugeMatcher = CreateSimpleAtomMatcher("M4", ATOM_4);
883 *config.add_atom_matcher() = gaugeMatcher;
884 AtomMatcher valueMatcher = CreateSimpleAtomMatcher("M5", ATOM_5);
885 *config.add_atom_matcher() = valueMatcher;
886 AtomMatcher kllMatcher = CreateSimpleAtomMatcher("M6", ATOM_6);
887 *config.add_atom_matcher() = kllMatcher;
888
889 Predicate predicate;
890 predicate.set_id(StringToId("P1"));
891 predicate.mutable_simple_predicate()->set_start(StringToId("M3_START"));
892 predicate.mutable_simple_predicate()->set_stop(StringToId("M3_STOP"));
893 FieldMatcher durDims = CreateDimensions(ATOM_3, {1});
894 *predicate.mutable_simple_predicate()->mutable_dimensions() = durDims;
895 *config.add_predicate() = predicate;
896
897 *config.add_event_metric() = createEventMetric("EVENT", eventMatcher.id(), nullopt);
898 CountMetric countMetric = createCountMetric("COUNT", countMatcher.id(), nullopt, {});
899 *countMetric.mutable_dimensions_in_what() =
900 CreateAttributionUidDimensions(ATOM_2, {Position::FIRST});
901 *config.add_count_metric() = countMetric;
902 DurationMetric durationMetric = createDurationMetric("DUR", predicate.id(), nullopt, {});
903 *durationMetric.mutable_dimensions_in_what() = durDims;
904 *config.add_duration_metric() = durationMetric;
905 GaugeMetric gaugeMetric = createGaugeMetric("GAUGE", gaugeMatcher.id(),
906 GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt);
907 *gaugeMetric.mutable_dimensions_in_what() = CreateDimensions(ATOM_4, {1});
908 *config.add_gauge_metric() = gaugeMetric;
909 ValueMetric valueMetric = createValueMetric("VALUE", valueMatcher, 2, nullopt, {});
910 valueMetric.set_skip_zero_diff_output(false);
911 *valueMetric.mutable_dimensions_in_what() =
912 CreateAttributionUidDimensions(ATOM_5, {Position::FIRST});
913 *config.add_value_metric() = valueMetric;
914 KllMetric kllMetric = createKllMetric("KLL", kllMatcher, 2, nullopt);
915 *kllMetric.mutable_dimensions_in_what() = CreateDimensions(ATOM_6, {1});
916 *config.add_kll_metric() = kllMetric;
917
918 int64_t startTimeNs = getElapsedRealtimeNs();
919 sp<UidMap> uidMap = new UidMap();
920 const int UID_1 = 11, UID_2 = 12, UID_3 = 13, UID_4 = 14, UID_5 = 15, UID_6 = 16, UID_7 = 17,
921 UID_8 = 18, UID_9 = 19;
922 int extraUids = 10; // Extra uids in the uid map that aren't referenced in the metric report.
923 int extraUidStart = 1000;
924 vector<int> uids = {UID_1, UID_2, UID_3, UID_4, UID_5, UID_6, UID_7, UID_8, UID_9};
925 int numUids = extraUids + uids.size();
926 for (int i = 0; i < extraUids; i++) {
927 uids.push_back(extraUidStart + i);
928 }
929 // We only care about the uids for this test. Give defaults to everything else.
930 vector<int64_t> versions(numUids, 0);
931 vector<string> versionStrings(numUids, "");
932 vector<string> apps(numUids, "");
933 vector<string> installers(numUids, "");
934 vector<uint8_t> hash;
935 vector<vector<uint8_t>> certHashes(numUids, hash);
936 uidMap->updateMap(startTimeNs,
937 createUidData(uids, versions, versionStrings, apps, installers, certHashes));
938
939 class FakePullAtomCallback : public BnPullAtomCallback {
940 public:
941 int pullNum = 1;
942 Status onPullAtom(int atomTag,
943 const shared_ptr<IPullAtomResultReceiver>& resultReceiver) override {
944 std::vector<StatsEventParcel> parcels;
945 AStatsEvent* event = makeAttributionStatsEvent(atomTag, 0, {UID_8}, {""}, pullNum, 0);
946 AStatsEvent_build(event);
947
948 size_t size;
949 uint8_t* buffer = AStatsEvent_getBuffer(event, &size);
950
951 StatsEventParcel p;
952 p.buffer.assign(buffer, buffer + size);
953 parcels.push_back(std::move(p));
954 AStatsEvent_release(event);
955 pullNum++;
956 resultReceiver->pullFinished(atomTag, /*success=*/true, parcels);
957 return Status::ok();
958 }
959 };
960
961 ConfigKey key(123, 987);
962 sp<StatsLogProcessor> p =
963 CreateStatsLogProcessor(startTimeNs, startTimeNs, config, key,
964 SharedRefBase::make<FakePullAtomCallback>(), ATOM_5, uidMap);
965
966 const uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
967 std::vector<std::shared_ptr<LogEvent>> events;
968 events.push_back(makeUidLogEvent(ATOM_1, startTimeNs + 10, UID_1, 0, 0));
969 events.push_back(makeUidLogEvent(ATOM_1, startTimeNs + 11, UID_2, 0, 0));
970 events.push_back(makeAttributionLogEvent(ATOM_2, startTimeNs + 12, {UID_3}, {""}, 0, 0));
971 events.push_back(makeUidLogEvent(ATOM_3, startTimeNs + 15, UID_5, 0, 0)); // start
972 events.push_back(makeUidLogEvent(ATOM_3, startTimeNs + 18, UID_5, 1, 0)); // stop
973 events.push_back(makeExtraUidsLogEvent(ATOM_4, startTimeNs + 20, UID_6, 0, 0, {UID_7}));
974 events.push_back(makeUidLogEvent(ATOM_6, startTimeNs + 22, UID_9, 0, 0));
975
976 events.push_back(
977 makeAttributionLogEvent(ATOM_2, startTimeNs + bucketSizeNs + 10, {UID_4}, {""}, 0, 0));
978
979 // Send log events to StatsLogProcessor.
980 for (auto& event : events) {
981 p->OnLogEvent(event.get());
982 }
983
984 int64_t dumpTimeNs = startTimeNs + bucketSizeNs + 100 * NS_PER_SEC;
985
986 {
987 ConfigMetricsReportList reports;
988 vector<uint8_t> buffer;
989 p->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
990 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
991 ASSERT_EQ(reports.reports_size(), 1);
992
993 UidMapping uidMappingProto = reports.reports(0).uid_map();
994 ASSERT_EQ(uidMappingProto.snapshots_size(), 1);
995 const RepeatedPtrField<PackageInfo>& pkgs = uidMappingProto.snapshots(0).package_info();
996 set<int32_t> actualUsedUids;
997 std::for_each(pkgs.begin(), pkgs.end(),
998 [&actualUsedUids](const PackageInfo& p) { actualUsedUids.insert(p.uid()); });
999
1000 EXPECT_THAT(actualUsedUids, UnorderedElementsAre(UID_1, UID_2, UID_3, UID_4, UID_5, UID_6,
1001 UID_7, UID_8, UID_9));
1002 }
1003
1004 // Verify the set is cleared and only contains the correct ids on the next dump.
1005 p->OnLogEvent(makeUidLogEvent(ATOM_1, dumpTimeNs + 10, UID_1, 0, 0).get());
1006 {
1007 ConfigMetricsReportList reports;
1008 vector<uint8_t> buffer;
1009 p->onDumpReport(key, dumpTimeNs + 20, true, false, ADB_DUMP, FAST, &buffer);
1010 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1011 ASSERT_EQ(reports.reports_size(), 1);
1012
1013 UidMapping uidMappingProto = reports.reports(0).uid_map();
1014 ASSERT_EQ(uidMappingProto.snapshots_size(), 1);
1015 const RepeatedPtrField<PackageInfo>& pkgs = uidMappingProto.snapshots(0).package_info();
1016 set<int32_t> actualUsedUids;
1017 std::for_each(pkgs.begin(), pkgs.end(),
1018 [&actualUsedUids](const PackageInfo& p) { actualUsedUids.insert(p.uid()); });
1019
1020 EXPECT_THAT(actualUsedUids, UnorderedElementsAre(UID_1));
1021 }
1022 }
1023
TEST(UidMapTest,TestUsedUidsFromMetricE2e)1024 TEST(UidMapTest, TestUsedUidsFromMetricE2e) {
1025 const int ATOM_1 = 1, ATOM_2 = 2, ATOM_3 = 3, ATOM_4 = 4, ATOM_5 = 10001, ATOM_6 = 6;
1026 StatsdConfig config;
1027 config.mutable_statsd_config_options()->set_omit_unused_uids_in_uidmap(true);
1028 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
1029 AtomMatcher eventMatcher = CreateSimpleAtomMatcher("M1", ATOM_1);
1030 *config.add_atom_matcher() = eventMatcher;
1031 AtomMatcher countMatcher = CreateSimpleAtomMatcher("M2", ATOM_2);
1032 *config.add_atom_matcher() = countMatcher;
1033 AtomMatcher durationStartMatcher = CreateSimpleAtomMatcher("M3_START", ATOM_3);
1034 auto fvmStart = durationStartMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
1035 fvmStart->set_field(2); // State field.
1036 fvmStart->set_eq_int(0);
1037 *config.add_atom_matcher() = durationStartMatcher;
1038 AtomMatcher durationStopMatcher = CreateSimpleAtomMatcher("M3_STOP", ATOM_3);
1039 auto fvmStop = durationStopMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
1040 fvmStop->set_field(2);
1041 fvmStop->set_eq_int(1);
1042 *config.add_atom_matcher() = durationStopMatcher;
1043 AtomMatcher gaugeMatcher = CreateSimpleAtomMatcher("M4", ATOM_4);
1044 *config.add_atom_matcher() = gaugeMatcher;
1045 AtomMatcher valueMatcher = CreateSimpleAtomMatcher("M5", ATOM_5);
1046 *config.add_atom_matcher() = valueMatcher;
1047 AtomMatcher kllMatcher = CreateSimpleAtomMatcher("M6", ATOM_6);
1048 *config.add_atom_matcher() = kllMatcher;
1049
1050 Predicate predicate;
1051 predicate.set_id(StringToId("P1"));
1052 predicate.mutable_simple_predicate()->set_start(StringToId("M3_START"));
1053 predicate.mutable_simple_predicate()->set_stop(StringToId("M3_STOP"));
1054 FieldMatcher durDims = CreateDimensions(ATOM_3, {1});
1055 *predicate.mutable_simple_predicate()->mutable_dimensions() = durDims;
1056 *config.add_predicate() = predicate;
1057
1058 EventMetric eventMetric = createEventMetric("EVENT", eventMatcher.id(), nullopt);
1059 *eventMetric.mutable_uid_fields() = CreateDimensions(ATOM_1, {1});
1060 *config.add_event_metric() = eventMetric;
1061 CountMetric countMetric = createCountMetric("COUNT", countMatcher.id(), nullopt, {});
1062 *countMetric.mutable_dimensions_in_what() = CreateDimensions(ATOM_2, {1});
1063 *countMetric.mutable_uid_fields() = CreateDimensions(ATOM_2, {1});
1064 *config.add_count_metric() = countMetric;
1065 DurationMetric durationMetric = createDurationMetric("DUR", predicate.id(), nullopt, {});
1066 *durationMetric.mutable_dimensions_in_what() = durDims;
1067 *durationMetric.mutable_uid_fields() = durDims;
1068 *config.add_duration_metric() = durationMetric;
1069 GaugeMetric gaugeMetric = createGaugeMetric("GAUGE", gaugeMatcher.id(),
1070 GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt);
1071 *gaugeMetric.mutable_dimensions_in_what() = CreateDimensions(ATOM_4, {1});
1072 *gaugeMetric.mutable_uid_fields() = CreateDimensions(ATOM_4, {1, 2});
1073 *config.add_gauge_metric() = gaugeMetric;
1074 ValueMetric valueMetric = createValueMetric("VALUE", valueMatcher, 2, nullopt, {});
1075 valueMetric.set_skip_zero_diff_output(false);
1076 *valueMetric.mutable_dimensions_in_what() = CreateDimensions(ATOM_5, {1});
1077 *valueMetric.mutable_uid_fields() = CreateDimensions(ATOM_5, {1});
1078 *config.add_value_metric() = valueMetric;
1079 KllMetric kllMetric = createKllMetric("KLL", kllMatcher, 2, nullopt);
1080 *kllMetric.mutable_dimensions_in_what() = CreateDimensions(ATOM_6, {1});
1081 *kllMetric.mutable_uid_fields() = CreateDimensions(ATOM_6, {1});
1082 *config.add_kll_metric() = kllMetric;
1083
1084 int64_t startTimeNs = getElapsedRealtimeNs();
1085 sp<UidMap> uidMap = new UidMap();
1086 const int UID_1 = 11, UID_2 = 12, UID_3 = 13, UID_4 = 14, UID_5 = 15, UID_6 = 16, UID_7 = 17,
1087 UID_8 = 18, UID_9 = 19;
1088 int extraUids = 10; // Extra uids in the uid map that aren't referenced in the metric report.
1089 int extraUidStart = 1000;
1090 vector<int> uids = {UID_1, UID_2, UID_3, UID_4, UID_5, UID_6, UID_7, UID_8, UID_9};
1091 int numUids = extraUids + uids.size();
1092 for (int i = 0; i < extraUids; i++) {
1093 uids.push_back(extraUidStart + i);
1094 }
1095 // We only care about the uids for this test. Give defaults to everything else.
1096 vector<int64_t> versions(numUids, 0);
1097 vector<string> versionStrings(numUids, "");
1098 vector<string> apps(numUids, "");
1099 vector<string> installers(numUids, "");
1100 vector<uint8_t> hash;
1101 vector<vector<uint8_t>> certHashes(numUids, hash);
1102 uidMap->updateMap(startTimeNs,
1103 createUidData(uids, versions, versionStrings, apps, installers, certHashes));
1104
1105 class FakePullAtomCallback : public BnPullAtomCallback {
1106 public:
1107 int pullNum = 1;
1108 Status onPullAtom(int atomTag,
1109 const shared_ptr<IPullAtomResultReceiver>& resultReceiver) override {
1110 std::vector<StatsEventParcel> parcels;
1111 AStatsEvent* event = makeTwoValueStatsEvent(atomTag, 0, UID_8, pullNum);
1112 AStatsEvent_build(event);
1113
1114 size_t size;
1115 uint8_t* buffer = AStatsEvent_getBuffer(event, &size);
1116
1117 StatsEventParcel p;
1118 p.buffer.assign(buffer, buffer + size);
1119 parcels.push_back(std::move(p));
1120 AStatsEvent_release(event);
1121 pullNum++;
1122 resultReceiver->pullFinished(atomTag, /*success=*/true, parcels);
1123 return Status::ok();
1124 }
1125 };
1126
1127 ConfigKey key(123, 987);
1128 sp<StatsLogProcessor> p =
1129 CreateStatsLogProcessor(startTimeNs, startTimeNs, config, key,
1130 SharedRefBase::make<FakePullAtomCallback>(), ATOM_5, uidMap);
1131
1132 const uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(TEN_MINUTES) * 1000000LL;
1133 std::vector<std::shared_ptr<LogEvent>> events;
1134 events.push_back(CreateTwoValueLogEvent(ATOM_1, startTimeNs + 10, UID_1, 0));
1135 events.push_back(CreateTwoValueLogEvent(ATOM_1, startTimeNs + 11, UID_2, 0));
1136 events.push_back(CreateTwoValueLogEvent(ATOM_2, startTimeNs + 12, UID_3, 0));
1137 events.push_back(CreateTwoValueLogEvent(ATOM_3, startTimeNs + 15, UID_5, 0)); // start
1138 events.push_back(CreateTwoValueLogEvent(ATOM_3, startTimeNs + 18, UID_5, 1)); // stop
1139 events.push_back(CreateTwoValueLogEvent(ATOM_4, startTimeNs + 20, UID_6, UID_7));
1140 events.push_back(CreateTwoValueLogEvent(ATOM_6, startTimeNs + 22, UID_9, 0));
1141
1142 events.push_back(CreateTwoValueLogEvent(ATOM_2, startTimeNs + bucketSizeNs + 10, UID_4, 0));
1143
1144 // Send log events to StatsLogProcessor.
1145 for (auto& event : events) {
1146 p->OnLogEvent(event.get());
1147 }
1148
1149 int64_t dumpTimeNs = startTimeNs + bucketSizeNs + 100 * NS_PER_SEC;
1150
1151 {
1152 ConfigMetricsReportList reports;
1153 vector<uint8_t> buffer;
1154 p->onDumpReport(key, dumpTimeNs, true, true, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
1155 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1156 ASSERT_EQ(reports.reports_size(), 1);
1157
1158 UidMapping uidMappingProto = reports.reports(0).uid_map();
1159 ASSERT_EQ(uidMappingProto.snapshots_size(), 1);
1160 const RepeatedPtrField<PackageInfo>& pkgs = uidMappingProto.snapshots(0).package_info();
1161 set<int32_t> actualUsedUids;
1162 std::for_each(pkgs.begin(), pkgs.end(),
1163 [&actualUsedUids](const PackageInfo& p) { actualUsedUids.insert(p.uid()); });
1164
1165 EXPECT_THAT(actualUsedUids, UnorderedElementsAre(UID_1, UID_2, UID_3, UID_4, UID_5, UID_6,
1166 UID_7, UID_8, UID_9));
1167 }
1168
1169 // Verify the set is cleared and only contains the correct ids on the next dump.
1170 p->OnLogEvent(CreateTwoValueLogEvent(ATOM_1, dumpTimeNs + 10, UID_1, 0).get());
1171 {
1172 ConfigMetricsReportList reports;
1173 vector<uint8_t> buffer;
1174 p->onDumpReport(key, dumpTimeNs + 20, true, false, ADB_DUMP, FAST, &buffer);
1175 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1176 ASSERT_EQ(reports.reports_size(), 1);
1177
1178 UidMapping uidMappingProto = reports.reports(0).uid_map();
1179 ASSERT_EQ(uidMappingProto.snapshots_size(), 1);
1180 const RepeatedPtrField<PackageInfo>& pkgs = uidMappingProto.snapshots(0).package_info();
1181 set<int32_t> actualUsedUids;
1182 std::for_each(pkgs.begin(), pkgs.end(),
1183 [&actualUsedUids](const PackageInfo& p) { actualUsedUids.insert(p.uid()); });
1184
1185 EXPECT_THAT(actualUsedUids, UnorderedElementsAre(UID_1));
1186 }
1187 }
1188
1189 } // anonymous namespace
1190 #else
1191 GTEST_LOG_(INFO) << "This test does nothing.\n";
1192 #endif
1193
1194 } // namespace statsd
1195 } // namespace os
1196 } // namespace android
1197