• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "StatsLogProcessor.h"
17 #include "config/ConfigKey.h"
18 #include "guardrail/StatsdStats.h"
19 #include "logd/LogEvent.h"
20 #include "hash.h"
21 #include "statslog_statsdtest.h"
22 #include "statsd_test_util.h"
23 
24 #include <android/util/ProtoOutputStream.h>
25 #include <gtest/gtest.h>
26 
27 #include <stdio.h>
28 
29 using namespace android;
30 
31 namespace android {
32 namespace os {
33 namespace statsd {
34 
35 using android::util::ProtoOutputStream;
36 using android::util::ProtoReader;
37 
38 #ifdef __ANDROID__
39 const string kApp1 = "app1.sharing.1";
40 const string kApp2 = "app2.sharing.1";
41 
TEST(UidMapTest,TestIsolatedUID)42 TEST(UidMapTest, TestIsolatedUID) {
43     sp<UidMap> m = new UidMap();
44     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
45     sp<AlarmMonitor> anomalyAlarmMonitor;
46     sp<AlarmMonitor> subscriberAlarmMonitor;
47     // Construct the processor with a no-op sendBroadcast function that does nothing.
48     StatsLogProcessor p(
49             m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
50             [](const ConfigKey& key) { return true; },
51             [](const int&, const vector<int64_t>&) { return true; });
52 
53     std::unique_ptr<LogEvent> addEvent = CreateIsolatedUidChangedEvent(
54             1 /*timestamp*/, 100 /*hostUid*/, 101 /*isolatedUid*/, 1 /*is_create*/);
55     EXPECT_EQ(101, m->getHostUidOrSelf(101));
56     p.OnLogEvent(addEvent.get());
57     EXPECT_EQ(100, m->getHostUidOrSelf(101));
58 
59     std::unique_ptr<LogEvent> removeEvent = CreateIsolatedUidChangedEvent(
60             1 /*timestamp*/, 100 /*hostUid*/, 101 /*isolatedUid*/, 0 /*is_create*/);
61     p.OnLogEvent(removeEvent.get());
62     EXPECT_EQ(101, m->getHostUidOrSelf(101));
63 }
64 
TEST(UidMapTest,TestMatching)65 TEST(UidMapTest, TestMatching) {
66     UidMap m;
67     const vector<int32_t> uids{1000, 1000};
68     const vector<int64_t> versions{4, 5};
69     const vector<String16> versionStrings{String16("v1"), String16("v1")};
70     const vector<String16> apps{String16(kApp1.c_str()), String16(kApp2.c_str())};
71     const vector<String16> installers{String16(""), String16("")};
72     const vector<vector<uint8_t>> certificateHashes{{}, {}};
73 
74     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
75                 certificateHashes);
76     EXPECT_TRUE(m.hasApp(1000, kApp1));
77     EXPECT_TRUE(m.hasApp(1000, kApp2));
78     EXPECT_FALSE(m.hasApp(1000, "not.app"));
79 
80     std::set<string> name_set = m.getAppNamesFromUid(1000u, true /* returnNormalized */);
81     ASSERT_EQ(name_set.size(), 2u);
82     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
83     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
84 
85     name_set = m.getAppNamesFromUid(12345, true /* returnNormalized */);
86     EXPECT_TRUE(name_set.empty());
87 }
88 
TEST(UidMapTest,TestAddAndRemove)89 TEST(UidMapTest, TestAddAndRemove) {
90     UidMap m;
91     const vector<int32_t> uids{1000, 1000};
92     const vector<int64_t> versions{4, 5};
93     const vector<String16> versionStrings{String16("v1"), String16("v1")};
94     const vector<String16> apps{String16(kApp1.c_str()), String16(kApp2.c_str())};
95     const vector<String16> installers{String16(""), String16("")};
96     const vector<vector<uint8_t>> certificateHashes{{}, {}};
97 
98     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
99                 certificateHashes);
100 
101     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
102     ASSERT_EQ(name_set.size(), 2u);
103     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
104     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
105 
106     // Update the app1 version.
107     m.updateApp(2, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""),
108                 /* certificateHash */ {});
109     EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
110 
111     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
112     ASSERT_EQ(name_set.size(), 2u);
113     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
114     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
115 
116     m.removeApp(3, String16(kApp1.c_str()), 1000);
117     EXPECT_FALSE(m.hasApp(1000, kApp1));
118     EXPECT_TRUE(m.hasApp(1000, kApp2));
119     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
120     ASSERT_EQ(name_set.size(), 1u);
121     EXPECT_TRUE(name_set.find(kApp1) == name_set.end());
122     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
123 
124     // Remove app2.
125     m.removeApp(4, String16(kApp2.c_str()), 1000);
126     EXPECT_FALSE(m.hasApp(1000, kApp1));
127     EXPECT_FALSE(m.hasApp(1000, kApp2));
128     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
129     EXPECT_TRUE(name_set.empty());
130 }
131 
TEST(UidMapTest,TestUpdateApp)132 TEST(UidMapTest, TestUpdateApp) {
133     UidMap m;
134     m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
135                 {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")},
136                 /* certificateHash */ {{}, {}});
137     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
138     ASSERT_EQ(name_set.size(), 2u);
139     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
140     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
141 
142     // Adds a new name for uid 1000.
143     m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""),
144                 /* certificateHash */ {});
145     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
146     ASSERT_EQ(name_set.size(), 3u);
147     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
148     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
149     EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
150     EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
151 
152     // This name is also reused by another uid 2000.
153     m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""),
154                 /* certificateHash */ {});
155     name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
156     ASSERT_EQ(name_set.size(), 1u);
157     EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
158     EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
159 }
160 
protoOutputStreamToUidMapping(ProtoOutputStream * proto,UidMapping * results)161 static void protoOutputStreamToUidMapping(ProtoOutputStream* proto, UidMapping* results) {
162     vector<uint8_t> bytes;
163     bytes.resize(proto->size());
164     size_t pos = 0;
165     sp<ProtoReader> reader = proto->data();
166     while (reader->readBuffer() != NULL) {
167         size_t toRead = reader->currentToRead();
168         std::memcpy(&((bytes)[pos]), reader->readBuffer(), toRead);
169         pos += toRead;
170         reader->move(toRead);
171     }
172     results->ParseFromArray(bytes.data(), bytes.size());
173 }
174 
175 // Test that uid map returns at least one snapshot even if we already obtained
176 // this snapshot from a previous call to getData.
TEST(UidMapTest,TestOutputIncludesAtLeastOneSnapshot)177 TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot) {
178     UidMap m;
179     // Initialize single config key.
180     ConfigKey config1(1, StringToId("config1"));
181     m.OnConfigUpdated(config1);
182     const vector<int32_t> uids{1000};
183     const vector<int64_t> versions{5};
184     const vector<String16> versionStrings{String16("v1")};
185     const vector<String16> apps{String16(kApp2.c_str())};
186     const vector<String16> installers{String16("")};
187     const vector<vector<uint8_t>> certificateHashes{{}};
188 
189     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
190                 certificateHashes);
191 
192     // Set the last timestamp for this config key to be newer.
193     m.mLastUpdatePerConfigKey[config1] = 2;
194 
195     ProtoOutputStream proto;
196     m.appendUidMap(/* timestamp */ 3, config1, /* includeVersionStrings */ true,
197                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
198                    /* str_set */ nullptr, &proto);
199 
200     // Check there's still a uidmap attached this one.
201     UidMapping results;
202     protoOutputStreamToUidMapping(&proto, &results);
203     ASSERT_EQ(1, results.snapshots_size());
204     EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
205 }
206 
TEST(UidMapTest,TestRemovedAppRetained)207 TEST(UidMapTest, TestRemovedAppRetained) {
208     UidMap m;
209     // Initialize single config key.
210     ConfigKey config1(1, StringToId("config1"));
211     m.OnConfigUpdated(config1);
212     const vector<int32_t> uids{1000};
213     const vector<int64_t> versions{5};
214     const vector<String16> versionStrings{String16("v5")};
215     const vector<String16> apps{String16(kApp2.c_str())};
216     const vector<String16> installers{String16("")};
217     const vector<vector<uint8_t>> certificateHashes{{}};
218 
219     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
220                 certificateHashes);
221     m.removeApp(2, String16(kApp2.c_str()), 1000);
222 
223     ProtoOutputStream proto;
224     m.appendUidMap(/* timestamp */ 3, config1, /* includeVersionStrings */ true,
225                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
226                    /* str_set */ nullptr, &proto);
227 
228     // Snapshot should still contain this item as deleted.
229     UidMapping results;
230     protoOutputStreamToUidMapping(&proto, &results);
231     ASSERT_EQ(1, results.snapshots(0).package_info_size());
232     EXPECT_EQ(true, results.snapshots(0).package_info(0).deleted());
233 }
234 
TEST(UidMapTest,TestRemovedAppOverGuardrail)235 TEST(UidMapTest, TestRemovedAppOverGuardrail) {
236     UidMap m;
237     // Initialize single config key.
238     ConfigKey config1(1, StringToId("config1"));
239     m.OnConfigUpdated(config1);
240     vector<int32_t> uids;
241     vector<int64_t> versions;
242     vector<String16> versionStrings;
243     vector<String16> installers;
244     vector<String16> apps;
245     vector<vector<uint8_t>> certificateHashes;
246     const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
247     for (int j = 0; j < maxDeletedApps + 10; j++) {
248         uids.push_back(j);
249         apps.push_back(String16(kApp1.c_str()));
250         versions.push_back(j);
251         versionStrings.push_back(String16("v"));
252         installers.push_back(String16(""));
253         certificateHashes.push_back({});
254     }
255     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
256                 certificateHashes);
257 
258     // First, verify that we have the expected number of items.
259     UidMapping results;
260     ProtoOutputStream proto;
261     m.appendUidMap(/* timestamp */ 3, config1, /* includeVersionStrings */ true,
262                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
263                    /* str_set */ nullptr, &proto);
264     protoOutputStreamToUidMapping(&proto, &results);
265     ASSERT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
266 
267     // Now remove all the apps.
268     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
269                 certificateHashes);
270     for (int j = 0; j < maxDeletedApps + 10; j++) {
271         m.removeApp(4, String16(kApp1.c_str()), j);
272     }
273 
274     proto.clear();
275     m.appendUidMap(/* timestamp */ 5, config1, /* includeVersionStrings */ true,
276                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
277                    /* str_set */ nullptr, &proto);
278     // Snapshot drops the first nine items.
279     protoOutputStreamToUidMapping(&proto, &results);
280     ASSERT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
281 }
282 
TEST(UidMapTest,TestClearingOutput)283 TEST(UidMapTest, TestClearingOutput) {
284     UidMap m;
285 
286     ConfigKey config1(1, StringToId("config1"));
287     ConfigKey config2(1, StringToId("config2"));
288 
289     m.OnConfigUpdated(config1);
290 
291     const vector<int32_t> uids{1000, 1000};
292     const vector<int64_t> versions{4, 5};
293     const vector<String16> versionStrings{String16("v4"), String16("v5")};
294     const vector<String16> apps{String16(kApp1.c_str()), String16(kApp2.c_str())};
295     const vector<String16> installers{String16(""), String16("")};
296     const vector<vector<uint8_t>> certificateHashes{{}, {}};
297     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
298                 certificateHashes);
299 
300     ProtoOutputStream proto;
301     m.appendUidMap(/* timestamp */ 2, config1, /* includeVersionStrings */ true,
302                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
303                    /* str_set */ nullptr, &proto);
304     UidMapping results;
305     protoOutputStreamToUidMapping(&proto, &results);
306     ASSERT_EQ(1, results.snapshots_size());
307 
308     // We have to keep at least one snapshot in memory at all times.
309     proto.clear();
310     m.appendUidMap(/* timestamp */ 2, config1, /* includeVersionStrings */ true,
311                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
312                    /* str_set */ nullptr, &proto);
313     protoOutputStreamToUidMapping(&proto, &results);
314     ASSERT_EQ(1, results.snapshots_size());
315 
316     // Now add another configuration.
317     m.OnConfigUpdated(config2);
318     m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""),
319                 /* certificateHash */ {});
320     ASSERT_EQ(1U, m.mChanges.size());
321     proto.clear();
322     m.appendUidMap(/* timestamp */ 6, config1, /* includeVersionStrings */ true,
323                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
324                    /* str_set */ nullptr, &proto);
325     protoOutputStreamToUidMapping(&proto, &results);
326     ASSERT_EQ(1, results.snapshots_size());
327     ASSERT_EQ(1, results.changes_size());
328     ASSERT_EQ(1U, m.mChanges.size());
329 
330     // Add another delta update.
331     m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""),
332                 /* certificateHash */ {});
333     ASSERT_EQ(2U, m.mChanges.size());
334 
335     // We still can't remove anything.
336     proto.clear();
337     m.appendUidMap(/* timestamp */ 8, config1, /* includeVersionStrings */ true,
338                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
339                    /* str_set */ nullptr, &proto);
340     protoOutputStreamToUidMapping(&proto, &results);
341     ASSERT_EQ(1, results.snapshots_size());
342     ASSERT_EQ(1, results.changes_size());
343     ASSERT_EQ(2U, m.mChanges.size());
344 
345     proto.clear();
346     m.appendUidMap(/* timestamp */ 9, config2, /* includeVersionStrings */ true,
347                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
348                    /* str_set */ nullptr, &proto);
349     protoOutputStreamToUidMapping(&proto, &results);
350     ASSERT_EQ(1, results.snapshots_size());
351     ASSERT_EQ(2, results.changes_size());
352     // At this point both should be cleared.
353     ASSERT_EQ(0U, m.mChanges.size());
354 }
355 
TEST(UidMapTest,TestMemoryComputed)356 TEST(UidMapTest, TestMemoryComputed) {
357     UidMap m;
358 
359     ConfigKey config1(1, StringToId("config1"));
360     m.OnConfigUpdated(config1);
361 
362     size_t startBytes = m.mBytesUsed;
363     const vector<int32_t> uids{1000};
364     const vector<int64_t> versions{1};
365     const vector<String16> versionStrings{String16("v1")};
366     const vector<String16> apps{String16(kApp1.c_str())};
367     const vector<String16> installers{String16("")};
368     const vector<vector<uint8_t>> certificateHashes{{}};
369     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
370                 certificateHashes);
371 
372     m.updateApp(3, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""),
373                 /* certificateHash */ {});
374 
375     ProtoOutputStream proto;
376     vector<uint8_t> bytes;
377     m.appendUidMap(/* timestamp */ 2, config1, /* includeVersionStrings */ true,
378                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
379                    /* str_set */ nullptr, &proto);
380     size_t prevBytes = m.mBytesUsed;
381 
382     m.appendUidMap(/* timestamp */ 4, config1, /* includeVersionStrings */ true,
383                    /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
384                    /* str_set */ nullptr, &proto);
385     EXPECT_TRUE(m.mBytesUsed < prevBytes);
386 }
387 
TEST(UidMapTest,TestMemoryGuardrail)388 TEST(UidMapTest, TestMemoryGuardrail) {
389     UidMap m;
390     string buf;
391 
392     ConfigKey config1(1, StringToId("config1"));
393     m.OnConfigUpdated(config1);
394 
395     size_t startBytes = m.mBytesUsed;
396     vector<int32_t> uids;
397     vector<int64_t> versions;
398     vector<String16> versionStrings;
399     vector<String16> installers;
400     vector<String16> apps;
401     vector<vector<uint8_t>> certificateHashes;
402     for (int i = 0; i < 100; i++) {
403         uids.push_back(1);
404         buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
405         apps.push_back(String16(buf.c_str()));
406         versions.push_back(1);
407         versionStrings.push_back(String16("v1"));
408         installers.push_back(String16(""));
409         certificateHashes.push_back({});
410     }
411     m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
412                 certificateHashes);
413 
414     m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
415                 String16("v2"), String16(""), /* certificateHash */ {});
416     ASSERT_EQ(1U, m.mChanges.size());
417 
418     // Now force deletion by limiting the memory to hold one delta change.
419     m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
420     m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4,
421                 String16("v4"), String16(""), /* certificateHash */ {});
422     ASSERT_EQ(1U, m.mChanges.size());
423 }
424 
425 #else
426 GTEST_LOG_(INFO) << "This test does nothing.\n";
427 #endif
428 
429 }  // namespace statsd
430 }  // namespace os
431 }  // namespace android
432