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