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