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