1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sys/mman.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21
22 #include <gtest/gtest.h>
23
24 #include <filesystem>
25 #include <string>
26 #include <vector>
27
28 #include <meminfo/androidprocheaps.h>
29 #include <meminfo/pageacct.h>
30 #include <meminfo/procmeminfo.h>
31 #include <meminfo/sysmeminfo.h>
32 #include <vintf/VintfObject.h>
33
34 #include <android-base/file.h>
35 #include <android-base/logging.h>
36 #include <android-base/properties.h>
37 #include <android-base/stringprintf.h>
38 #include <android-base/strings.h>
39
40 using namespace std;
41 using namespace android::meminfo;
42 using android::vintf::KernelVersion;
43 using android::vintf::RuntimeInfo;
44 using android::vintf::VintfObject;
45
46 namespace fs = std::filesystem;
47
48 pid_t pid = -1;
49
TEST(ProcMemInfo,TestWorkingTestReset)50 TEST(ProcMemInfo, TestWorkingTestReset) {
51 // Expect reset to succeed
52 EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
53 }
54
TEST(ProcMemInfo,UsageEmpty)55 TEST(ProcMemInfo, UsageEmpty) {
56 // If we created the object for getting working set,
57 // the usage must be empty
58 ProcMemInfo proc_mem(pid, true);
59 const MemUsage& usage = proc_mem.Usage();
60 EXPECT_EQ(usage.rss, 0);
61 EXPECT_EQ(usage.vss, 0);
62 EXPECT_EQ(usage.pss, 0);
63 EXPECT_EQ(usage.uss, 0);
64 EXPECT_EQ(usage.swap, 0);
65 }
66
TEST(ProcMemInfo,MapsNotEmpty)67 TEST(ProcMemInfo, MapsNotEmpty) {
68 // Make sure the process maps are never empty
69 ProcMemInfo proc_mem(pid);
70 const std::vector<Vma>& maps = proc_mem.Maps();
71 EXPECT_FALSE(maps.empty());
72 }
73
TEST(ProcMemInfo,MapsUsageNotEmpty)74 TEST(ProcMemInfo, MapsUsageNotEmpty) {
75 ProcMemInfo proc_mem(pid);
76 const std::vector<Vma>& maps = proc_mem.Maps();
77 EXPECT_FALSE(maps.empty());
78 uint64_t total_pss = 0;
79 uint64_t total_rss = 0;
80 uint64_t total_uss = 0;
81 for (auto& map : maps) {
82 ASSERT_NE(0, map.usage.vss);
83 total_rss += map.usage.rss;
84 total_pss += map.usage.pss;
85 total_uss += map.usage.uss;
86 }
87
88 // Crude check that stats are actually being read.
89 EXPECT_NE(0, total_rss) << "RSS zero for all maps, that is not possible.";
90 EXPECT_NE(0, total_pss) << "PSS zero for all maps, that is not possible.";
91 EXPECT_NE(0, total_uss) << "USS zero for all maps, that is not possible.";
92 }
93
TEST(ProcMemInfo,MapsUsageEmpty)94 TEST(ProcMemInfo, MapsUsageEmpty) {
95 ProcMemInfo proc_mem(pid);
96 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
97 EXPECT_FALSE(maps.empty());
98 // Verify that all usage stats are zero in every map.
99 for (auto& map : maps) {
100 ASSERT_EQ(0, map.usage.vss);
101 ASSERT_EQ(0, map.usage.rss);
102 ASSERT_EQ(0, map.usage.pss);
103 ASSERT_EQ(0, map.usage.uss);
104 ASSERT_EQ(0, map.usage.swap);
105 ASSERT_EQ(0, map.usage.swap_pss);
106 ASSERT_EQ(0, map.usage.private_clean);
107 ASSERT_EQ(0, map.usage.private_dirty);
108 ASSERT_EQ(0, map.usage.shared_clean);
109 ASSERT_EQ(0, map.usage.shared_dirty);
110 }
111 }
112
TEST(ProcMemInfo,MapsUsageFillInLater)113 TEST(ProcMemInfo, MapsUsageFillInLater) {
114 ProcMemInfo proc_mem(pid);
115 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
116 EXPECT_FALSE(maps.empty());
117 for (auto& map : maps) {
118 Vma update_map(map);
119 ASSERT_EQ(map.start, update_map.start);
120 ASSERT_EQ(map.end, update_map.end);
121 ASSERT_EQ(map.offset, update_map.offset);
122 ASSERT_EQ(map.flags, update_map.flags);
123 ASSERT_EQ(map.name, update_map.name);
124 ASSERT_EQ(0, update_map.usage.vss);
125 ASSERT_EQ(0, update_map.usage.rss);
126 ASSERT_EQ(0, update_map.usage.pss);
127 ASSERT_EQ(0, update_map.usage.uss);
128 ASSERT_EQ(0, update_map.usage.swap);
129 ASSERT_EQ(0, update_map.usage.swap_pss);
130 ASSERT_EQ(0, update_map.usage.private_clean);
131 ASSERT_EQ(0, update_map.usage.private_dirty);
132 ASSERT_EQ(0, update_map.usage.shared_clean);
133 ASSERT_EQ(0, update_map.usage.shared_dirty);
134 ASSERT_TRUE(proc_mem.FillInVmaStats(update_map));
135 // Check that at least one usage stat was updated.
136 ASSERT_NE(0, update_map.usage.vss);
137 }
138 }
139
TEST(ProcMemInfo,MapsUsageFillInAll)140 TEST(ProcMemInfo, MapsUsageFillInAll) {
141 ProcMemInfo proc_mem(pid);
142 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
143 EXPECT_FALSE(maps.empty());
144 for (auto& map : maps) {
145 ASSERT_EQ(0, map.usage.vss);
146 ASSERT_EQ(0, map.usage.rss);
147 ASSERT_EQ(0, map.usage.pss);
148 ASSERT_EQ(0, map.usage.uss);
149 ASSERT_EQ(0, map.usage.swap);
150 ASSERT_EQ(0, map.usage.swap_pss);
151 ASSERT_EQ(0, map.usage.private_clean);
152 ASSERT_EQ(0, map.usage.private_dirty);
153 ASSERT_EQ(0, map.usage.shared_clean);
154 ASSERT_EQ(0, map.usage.shared_dirty);
155 }
156 // GetUsageStats' non-default parameter get_wss is false by default in
157 // ProcMemInfo's constructor.
158 ASSERT_TRUE(proc_mem.GetUsageStats(false));
159 for (auto& map : maps) {
160 // Check that at least one usage stat was updated.
161 ASSERT_NE(0, map.usage.vss);
162 }
163 }
164
TEST(ProcMemInfo,PageMapPresent)165 TEST(ProcMemInfo, PageMapPresent) {
166 static constexpr size_t kNumPages = 20;
167 size_t pagesize = getpagesize();
168 void* ptr = mmap(nullptr, pagesize * (kNumPages + 2), PROT_READ | PROT_WRITE,
169 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
170 ASSERT_NE(MAP_FAILED, ptr);
171
172 // Unmap the first page and the last page so that we guarantee this
173 // map is in a map by itself.
174 ASSERT_EQ(0, munmap(ptr, pagesize));
175 uintptr_t addr = reinterpret_cast<uintptr_t>(ptr) + pagesize;
176 ASSERT_EQ(0, munmap(reinterpret_cast<void*>(addr + kNumPages * pagesize), pagesize));
177
178 ProcMemInfo proc_mem(getpid());
179 const std::vector<Vma>& maps = proc_mem.MapsWithoutUsageStats();
180 ASSERT_FALSE(maps.empty());
181
182 // Find the vma associated with our previously created map.
183 const Vma* test_vma = nullptr;
184 for (const Vma& vma : maps) {
185 if (vma.start == addr) {
186 test_vma = &vma;
187 break;
188 }
189 }
190 ASSERT_TRUE(test_vma != nullptr) << "Cannot find test map.";
191
192 // Verify that none of the pages are listed as present.
193 std::vector<uint64_t> pagemap;
194 ASSERT_TRUE(proc_mem.PageMap(*test_vma, &pagemap));
195 ASSERT_EQ(kNumPages, pagemap.size());
196 for (size_t i = 0; i < pagemap.size(); i++) {
197 EXPECT_FALSE(android::meminfo::page_present(pagemap[i]))
198 << "Page " << i << " is present and it should not be.";
199 }
200
201 // Make some of the pages present and verify that we see them
202 // as present.
203 uint8_t* data = reinterpret_cast<uint8_t*>(addr);
204 data[0] = 1;
205 data[pagesize * 5] = 1;
206 data[pagesize * 11] = 1;
207
208 ASSERT_TRUE(proc_mem.PageMap(*test_vma, &pagemap));
209 ASSERT_EQ(kNumPages, pagemap.size());
210 for (size_t i = 0; i < pagemap.size(); i++) {
211 if (i == 0 || i == 5 || i == 11) {
212 EXPECT_TRUE(android::meminfo::page_present(pagemap[i]))
213 << "Page " << i << " is not present and it should be.";
214 } else {
215 EXPECT_FALSE(android::meminfo::page_present(pagemap[i]))
216 << "Page " << i << " is present and it should not be.";
217 }
218 }
219
220 ASSERT_EQ(0, munmap(reinterpret_cast<void*>(addr), kNumPages * pagesize));
221 }
222
TEST(ProcMemInfo,WssEmpty)223 TEST(ProcMemInfo, WssEmpty) {
224 // If we created the object for getting usage,
225 // the working set must be empty
226 ProcMemInfo proc_mem(pid, false);
227 const MemUsage& wss = proc_mem.Wss();
228 EXPECT_EQ(wss.rss, 0);
229 EXPECT_EQ(wss.vss, 0);
230 EXPECT_EQ(wss.pss, 0);
231 EXPECT_EQ(wss.uss, 0);
232 EXPECT_EQ(wss.swap, 0);
233 }
234
TEST(ProcMemInfo,SwapOffsetsEmpty)235 TEST(ProcMemInfo, SwapOffsetsEmpty) {
236 // If we created the object for getting working set,
237 // the swap offsets must be empty
238 ProcMemInfo proc_mem(pid, true);
239 const std::vector<uint64_t>& swap_offsets = proc_mem.SwapOffsets();
240 EXPECT_EQ(swap_offsets.size(), 0);
241 }
242
TEST(ProcMemInfo,IsSmapsSupportedTest)243 TEST(ProcMemInfo, IsSmapsSupportedTest) {
244 // Check if /proc/self/smaps_rollup exists using the API.
245 bool supported = IsSmapsRollupSupported();
246 EXPECT_EQ(!access("/proc/self/smaps_rollup", F_OK | R_OK), supported);
247 }
248
TEST(ProcMemInfo,SmapsOrRollupTest)249 TEST(ProcMemInfo, SmapsOrRollupTest) {
250 // Make sure we can parse 'smaps_rollup' correctly
251 std::string rollup =
252 R"rollup(12c00000-7fe859e000 ---p 00000000 00:00 0 [rollup]
253 Rss: 331908 kB
254 Pss: 202052 kB
255 Shared_Clean: 158492 kB
256 Shared_Dirty: 18928 kB
257 Private_Clean: 90472 kB
258 Private_Dirty: 64016 kB
259 Referenced: 318700 kB
260 Anonymous: 81984 kB
261 AnonHugePages: 0 kB
262 Shared_Hugetlb: 0 kB
263 Private_Hugetlb: 0 kB
264 Swap: 5344 kB
265 SwapPss: 442 kB
266 Locked: 1523537 kB)rollup";
267
268 TemporaryFile tf;
269 ASSERT_TRUE(tf.fd != -1);
270 ASSERT_TRUE(::android::base::WriteStringToFd(rollup, tf.fd));
271
272 MemUsage stats;
273 ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
274 EXPECT_EQ(stats.rss, 331908);
275 EXPECT_EQ(stats.pss, 202052);
276 EXPECT_EQ(stats.uss, 154488);
277 EXPECT_EQ(stats.private_clean, 90472);
278 EXPECT_EQ(stats.private_dirty, 64016);
279 EXPECT_EQ(stats.swap_pss, 442);
280 }
281
TEST(ProcMemInfo,SmapsOrRollupSmapsTest)282 TEST(ProcMemInfo, SmapsOrRollupSmapsTest) {
283 // Make sure /proc/<pid>/smaps is parsed correctly
284 std::string smaps =
285 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
286 Name: [anon:dalvik-main space (region space)]
287 Size: 8448 kB
288 KernelPageSize: 4 kB
289 MMUPageSize: 4 kB
290 Rss: 2652 kB
291 Pss: 2652 kB
292 Shared_Clean: 840 kB
293 Shared_Dirty: 40 kB
294 Private_Clean: 84 kB
295 Private_Dirty: 2652 kB
296 Referenced: 2652 kB
297 Anonymous: 2652 kB
298 AnonHugePages: 0 kB
299 ShmemPmdMapped: 0 kB
300 Shared_Hugetlb: 0 kB
301 Private_Hugetlb: 0 kB
302 Swap: 102 kB
303 SwapPss: 70 kB
304 Locked: 2652 kB
305 VmFlags: rd wr mr mw me ac
306 )smaps";
307
308 TemporaryFile tf;
309 ASSERT_TRUE(tf.fd != -1);
310 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
311
312 MemUsage stats;
313 ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
314 EXPECT_EQ(stats.rss, 2652);
315 EXPECT_EQ(stats.pss, 2652);
316 EXPECT_EQ(stats.uss, 2736);
317 EXPECT_EQ(stats.private_clean, 84);
318 EXPECT_EQ(stats.private_dirty, 2652);
319 EXPECT_EQ(stats.swap_pss, 70);
320 }
321
TEST(ProcMemInfo,SmapsOrRollupPssRollupTest)322 TEST(ProcMemInfo, SmapsOrRollupPssRollupTest) {
323 // Make sure /proc/<pid>/smaps is parsed correctly
324 // to get the PSS
325 std::string smaps =
326 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
327 Name: [anon:dalvik-main space (region space)]
328 Size: 8448 kB
329 KernelPageSize: 4 kB
330 MMUPageSize: 4 kB
331 Rss: 2652 kB
332 Pss: 2652 kB
333 Shared_Clean: 840 kB
334 Shared_Dirty: 40 kB
335 Private_Clean: 84 kB
336 Private_Dirty: 2652 kB
337 Referenced: 2652 kB
338 Anonymous: 2652 kB
339 AnonHugePages: 0 kB
340 ShmemPmdMapped: 0 kB
341 Shared_Hugetlb: 0 kB
342 Private_Hugetlb: 0 kB
343 Swap: 102 kB
344 SwapPss: 70 kB
345 Locked: 2652 kB
346 VmFlags: rd wr mr mw me ac
347 )smaps";
348
349 TemporaryFile tf;
350 ASSERT_TRUE(tf.fd != -1);
351 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
352
353 uint64_t pss;
354 ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true);
355 EXPECT_EQ(pss, 2652);
356 }
357
TEST(ProcMemInfo,SmapsOrRollupPssSmapsTest)358 TEST(ProcMemInfo, SmapsOrRollupPssSmapsTest) {
359 // Correctly parse smaps file to gather pss
360 std::string exec_dir = ::android::base::GetExecutableDirectory();
361 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
362
363 uint64_t pss;
364 ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true);
365 EXPECT_EQ(pss, 19119);
366 }
367
TEST(ProcMemInfo,StatusVmRSSTest)368 TEST(ProcMemInfo, StatusVmRSSTest) {
369 std::string exec_dir = ::android::base::GetExecutableDirectory();
370 std::string path = ::android::base::StringPrintf("%s/testdata1/status", exec_dir.c_str());
371
372 uint64_t rss;
373 ASSERT_EQ(StatusVmRSSFromFile(path, &rss), true);
374 EXPECT_EQ(rss, 730764);
375 }
376
TEST(ProcMemInfo,StatusVmRSSBogusFileTest)377 TEST(ProcMemInfo, StatusVmRSSBogusFileTest) {
378 std::string exec_dir = ::android::base::GetExecutableDirectory();
379 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps", exec_dir.c_str());
380
381 uint64_t rss;
382 ASSERT_EQ(StatusVmRSSFromFile(path, &rss), false);
383 }
384
TEST(ProcMemInfo,ForEachExistingVmaTest)385 TEST(ProcMemInfo, ForEachExistingVmaTest) {
386 std::string exec_dir = ::android::base::GetExecutableDirectory();
387 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
388 ProcMemInfo proc_mem(pid);
389 // Populate maps_.
390 proc_mem.Smaps(path);
391 std::vector<Vma> vmas;
392 auto collect_vmas = [&](const Vma& v) {
393 vmas.push_back(v);
394 return true;
395 };
396 EXPECT_TRUE(proc_mem.ForEachExistingVma(collect_vmas));
397
398 // The size of vmas is not checked because Smaps() will return 5 vmas on x86
399 // and 6 vmas otherwise, as [vsyscall] is not processed on x86.
400
401 // Expect values to be equal to what we have in testdata1/smaps_short
402 // Check for names
403 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
404 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
405 EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
406 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
407 << "Unknown map name " << vmas[2].name;
408 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
409 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
410
411 // Check start address
412 EXPECT_EQ(vmas[0].start, 0x54c00000);
413 EXPECT_EQ(vmas[1].start, 0x701ea000);
414 EXPECT_EQ(vmas[2].start, 0x70074dd8d000);
415 EXPECT_EQ(vmas[3].start, 0x700755a2d000);
416 EXPECT_EQ(vmas[4].start, 0x7007f85b0000);
417
418 // Check end address
419 EXPECT_EQ(vmas[0].end, 0x56c00000);
420 EXPECT_EQ(vmas[1].end, 0x70cdb000);
421 EXPECT_EQ(vmas[2].end, 0x70074ee0d000);
422 EXPECT_EQ(vmas[3].end, 0x700755a6e000);
423 EXPECT_EQ(vmas[4].end, 0x7007f8b9b000);
424
425 // Check Flags
426 EXPECT_EQ(vmas[0].flags, PROT_READ | PROT_EXEC);
427 EXPECT_EQ(vmas[1].flags, PROT_READ | PROT_WRITE);
428 EXPECT_EQ(vmas[2].flags, PROT_READ | PROT_WRITE);
429 EXPECT_EQ(vmas[3].flags, PROT_READ | PROT_EXEC);
430 EXPECT_EQ(vmas[4].flags, PROT_READ | PROT_EXEC);
431
432 // Check Shared
433 EXPECT_FALSE(vmas[0].is_shared);
434 EXPECT_FALSE(vmas[1].is_shared);
435 EXPECT_FALSE(vmas[2].is_shared);
436 EXPECT_FALSE(vmas[3].is_shared);
437 EXPECT_FALSE(vmas[4].is_shared);
438
439 // Check Offset
440 EXPECT_EQ(vmas[0].offset, 0x0);
441 EXPECT_EQ(vmas[1].offset, 0x0);
442 EXPECT_EQ(vmas[2].offset, 0x0);
443 EXPECT_EQ(vmas[3].offset, 0x00016000);
444 EXPECT_EQ(vmas[4].offset, 0x001ee000);
445
446 // Check Inode
447 EXPECT_EQ(vmas[0].inode, 0);
448 EXPECT_EQ(vmas[1].inode, 3165);
449 EXPECT_EQ(vmas[2].inode, 0);
450 EXPECT_EQ(vmas[3].inode, 1947);
451 EXPECT_EQ(vmas[4].inode, 1537);
452
453 // Check smaps specific fields
454 ASSERT_EQ(vmas[0].usage.vss, 32768);
455 EXPECT_EQ(vmas[1].usage.vss, 11204);
456 EXPECT_EQ(vmas[2].usage.vss, 16896);
457 EXPECT_EQ(vmas[3].usage.vss, 260);
458 EXPECT_EQ(vmas[4].usage.vss, 6060);
459
460 EXPECT_EQ(vmas[0].usage.rss, 2048);
461 EXPECT_EQ(vmas[1].usage.rss, 11188);
462 EXPECT_EQ(vmas[2].usage.rss, 15272);
463 EXPECT_EQ(vmas[3].usage.rss, 260);
464 EXPECT_EQ(vmas[4].usage.rss, 4132);
465
466 EXPECT_EQ(vmas[0].usage.pss, 113);
467 EXPECT_EQ(vmas[1].usage.pss, 2200);
468 EXPECT_EQ(vmas[2].usage.pss, 15272);
469 EXPECT_EQ(vmas[3].usage.pss, 260);
470 EXPECT_EQ(vmas[4].usage.pss, 1274);
471
472 EXPECT_EQ(vmas[0].usage.uss, 0);
473 EXPECT_EQ(vmas[1].usage.uss, 1660);
474 EXPECT_EQ(vmas[2].usage.uss, 15272);
475 EXPECT_EQ(vmas[3].usage.uss, 260);
476 EXPECT_EQ(vmas[4].usage.uss, 0);
477
478 EXPECT_EQ(vmas[0].usage.private_clean, 0);
479 EXPECT_EQ(vmas[1].usage.private_clean, 0);
480 EXPECT_EQ(vmas[2].usage.private_clean, 0);
481 EXPECT_EQ(vmas[3].usage.private_clean, 260);
482 EXPECT_EQ(vmas[4].usage.private_clean, 0);
483
484 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
485 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
486 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
487 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
488 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
489
490 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
491 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
492 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
493 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
494 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
495
496 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
497 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
498 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
499 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
500 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
501
502 EXPECT_EQ(vmas[0].usage.swap, 0);
503 EXPECT_EQ(vmas[1].usage.swap, 0);
504 EXPECT_EQ(vmas[2].usage.swap, 0);
505 EXPECT_EQ(vmas[3].usage.swap, 0);
506 EXPECT_EQ(vmas[4].usage.swap, 0);
507
508 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
509 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
510 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
511 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
512 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
513
514 #ifndef __x86_64__
515 // vmas[5] will not exist on x86, as [vsyscall] would not be processed.
516 EXPECT_EQ(vmas[5].name, "[vsyscall]");
517 EXPECT_EQ(vmas[5].start, 0xffffffffff600000);
518 EXPECT_EQ(vmas[5].end, 0xffffffffff601000);
519 EXPECT_EQ(vmas[5].flags, PROT_READ | PROT_EXEC);
520 EXPECT_FALSE(vmas[5].is_shared);
521 EXPECT_EQ(vmas[5].offset, 0x0);
522 EXPECT_EQ(vmas[5].inode, 0);
523 EXPECT_EQ(vmas[5].usage.vss, 4);
524 EXPECT_EQ(vmas[5].usage.rss, 0);
525 EXPECT_EQ(vmas[5].usage.pss, 0);
526 EXPECT_EQ(vmas[5].usage.uss, 0);
527 EXPECT_EQ(vmas[5].usage.private_clean, 0);
528 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
529 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
530 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
531 EXPECT_EQ(vmas[5].usage.swap, 0);
532 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
533 #endif
534 }
535
TEST(ProcMemInfo,ForEachVmaFromFile_SmapsTest)536 TEST(ProcMemInfo, ForEachVmaFromFile_SmapsTest) {
537 // Parse smaps file correctly to make callbacks for each virtual memory area (vma)
538 std::string exec_dir = ::android::base::GetExecutableDirectory();
539 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
540 ProcMemInfo proc_mem(pid);
541
542 std::vector<Vma> vmas;
543 auto collect_vmas = [&](const Vma& v) {
544 vmas.push_back(v);
545 return true;
546 };
547 ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas));
548
549 // We should get a total of 6 vmas
550 ASSERT_EQ(vmas.size(), 6);
551
552 // Expect values to be equal to what we have in testdata1/smaps_short
553 // Check for names
554 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
555 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
556 EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
557 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
558 << "Unknown map name " << vmas[2].name;
559 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
560 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
561 EXPECT_EQ(vmas[5].name, "[vsyscall]");
562
563 // Check start address
564 EXPECT_EQ(vmas[0].start, 0x54c00000);
565 EXPECT_EQ(vmas[1].start, 0x701ea000);
566 EXPECT_EQ(vmas[2].start, 0x70074dd8d000);
567 EXPECT_EQ(vmas[3].start, 0x700755a2d000);
568 EXPECT_EQ(vmas[4].start, 0x7007f85b0000);
569 EXPECT_EQ(vmas[5].start, 0xffffffffff600000);
570
571 // Check end address
572 EXPECT_EQ(vmas[0].end, 0x56c00000);
573 EXPECT_EQ(vmas[1].end, 0x70cdb000);
574 EXPECT_EQ(vmas[2].end, 0x70074ee0d000);
575 EXPECT_EQ(vmas[3].end, 0x700755a6e000);
576 EXPECT_EQ(vmas[4].end, 0x7007f8b9b000);
577 EXPECT_EQ(vmas[5].end, 0xffffffffff601000);
578
579 // Check Flags
580 EXPECT_EQ(vmas[0].flags, PROT_READ | PROT_EXEC);
581 EXPECT_EQ(vmas[1].flags, PROT_READ | PROT_WRITE);
582 EXPECT_EQ(vmas[2].flags, PROT_READ | PROT_WRITE);
583 EXPECT_EQ(vmas[3].flags, PROT_READ | PROT_EXEC);
584 EXPECT_EQ(vmas[4].flags, PROT_READ | PROT_EXEC);
585 EXPECT_EQ(vmas[5].flags, PROT_READ | PROT_EXEC);
586
587 // Check Shared
588 EXPECT_FALSE(vmas[0].is_shared);
589 EXPECT_FALSE(vmas[1].is_shared);
590 EXPECT_FALSE(vmas[2].is_shared);
591 EXPECT_FALSE(vmas[3].is_shared);
592 EXPECT_FALSE(vmas[4].is_shared);
593 EXPECT_FALSE(vmas[5].is_shared);
594
595 // Check Offset
596 EXPECT_EQ(vmas[0].offset, 0x0);
597 EXPECT_EQ(vmas[1].offset, 0x0);
598 EXPECT_EQ(vmas[2].offset, 0x0);
599 EXPECT_EQ(vmas[3].offset, 0x00016000);
600 EXPECT_EQ(vmas[4].offset, 0x001ee000);
601 EXPECT_EQ(vmas[5].offset, 0x0);
602
603 // Check Inode
604 EXPECT_EQ(vmas[0].inode, 0);
605 EXPECT_EQ(vmas[1].inode, 3165);
606 EXPECT_EQ(vmas[2].inode, 0);
607 EXPECT_EQ(vmas[3].inode, 1947);
608 EXPECT_EQ(vmas[4].inode, 1537);
609 EXPECT_EQ(vmas[5].inode, 0);
610
611 // Check smaps specific fields
612 ASSERT_EQ(vmas[0].usage.vss, 32768);
613 EXPECT_EQ(vmas[1].usage.vss, 11204);
614 EXPECT_EQ(vmas[2].usage.vss, 16896);
615 EXPECT_EQ(vmas[3].usage.vss, 260);
616 EXPECT_EQ(vmas[4].usage.vss, 6060);
617 EXPECT_EQ(vmas[5].usage.vss, 4);
618
619 EXPECT_EQ(vmas[0].usage.rss, 2048);
620 EXPECT_EQ(vmas[1].usage.rss, 11188);
621 EXPECT_EQ(vmas[2].usage.rss, 15272);
622 EXPECT_EQ(vmas[3].usage.rss, 260);
623 EXPECT_EQ(vmas[4].usage.rss, 4132);
624 EXPECT_EQ(vmas[5].usage.rss, 0);
625
626 EXPECT_EQ(vmas[0].usage.pss, 113);
627 EXPECT_EQ(vmas[1].usage.pss, 2200);
628 EXPECT_EQ(vmas[2].usage.pss, 15272);
629 EXPECT_EQ(vmas[3].usage.pss, 260);
630 EXPECT_EQ(vmas[4].usage.pss, 1274);
631 EXPECT_EQ(vmas[5].usage.pss, 0);
632
633 EXPECT_EQ(vmas[0].usage.uss, 0);
634 EXPECT_EQ(vmas[1].usage.uss, 1660);
635 EXPECT_EQ(vmas[2].usage.uss, 15272);
636 EXPECT_EQ(vmas[3].usage.uss, 260);
637 EXPECT_EQ(vmas[4].usage.uss, 0);
638 EXPECT_EQ(vmas[5].usage.uss, 0);
639
640 EXPECT_EQ(vmas[0].usage.private_clean, 0);
641 EXPECT_EQ(vmas[1].usage.private_clean, 0);
642 EXPECT_EQ(vmas[2].usage.private_clean, 0);
643 EXPECT_EQ(vmas[3].usage.private_clean, 260);
644 EXPECT_EQ(vmas[4].usage.private_clean, 0);
645 EXPECT_EQ(vmas[5].usage.private_clean, 0);
646
647 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
648 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
649 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
650 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
651 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
652 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
653
654 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
655 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
656 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
657 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
658 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
659 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
660
661 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
662 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
663 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
664 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
665 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
666 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
667
668 EXPECT_EQ(vmas[0].usage.swap, 0);
669 EXPECT_EQ(vmas[1].usage.swap, 0);
670 EXPECT_EQ(vmas[2].usage.swap, 0);
671 EXPECT_EQ(vmas[3].usage.swap, 0);
672 EXPECT_EQ(vmas[4].usage.swap, 0);
673 EXPECT_EQ(vmas[5].usage.swap, 0);
674
675 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
676 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
677 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
678 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
679 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
680 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
681 }
682
TEST(ProcMemInfo,ForEachVmaFromFile_MapsTest)683 TEST(ProcMemInfo, ForEachVmaFromFile_MapsTest) {
684 // Parse maps file correctly to make callbacks for each virtual memory area (vma)
685 std::string exec_dir = ::android::base::GetExecutableDirectory();
686 std::string path = ::android::base::StringPrintf("%s/testdata1/maps_short", exec_dir.c_str());
687 ProcMemInfo proc_mem(pid);
688
689 std::vector<Vma> vmas;
690 auto collect_vmas = [&](const Vma& v) {
691 vmas.push_back(v);
692 return true;
693 };
694 ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas, false));
695
696 // We should get a total of 6 vmas
697 ASSERT_EQ(vmas.size(), 6);
698
699 // Expect values to be equal to what we have in testdata1/maps_short
700 // Check for names
701 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
702 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
703 EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
704 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
705 << "Unknown map name " << vmas[2].name;
706 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
707 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
708 EXPECT_EQ(vmas[5].name, "[vsyscall]");
709
710 // Check start address
711 EXPECT_EQ(vmas[0].start, 0x54c00000);
712 EXPECT_EQ(vmas[1].start, 0x701ea000);
713 EXPECT_EQ(vmas[2].start, 0x70074dd8d000);
714 EXPECT_EQ(vmas[3].start, 0x700755a2d000);
715 EXPECT_EQ(vmas[4].start, 0x7007f85b0000);
716 EXPECT_EQ(vmas[5].start, 0xffffffffff600000);
717
718 // Check end address
719 EXPECT_EQ(vmas[0].end, 0x56c00000);
720 EXPECT_EQ(vmas[1].end, 0x70cdb000);
721 EXPECT_EQ(vmas[2].end, 0x70074ee0d000);
722 EXPECT_EQ(vmas[3].end, 0x700755a6e000);
723 EXPECT_EQ(vmas[4].end, 0x7007f8b9b000);
724 EXPECT_EQ(vmas[5].end, 0xffffffffff601000);
725
726 // Check Flags
727 EXPECT_EQ(vmas[0].flags, PROT_READ | PROT_EXEC);
728 EXPECT_EQ(vmas[1].flags, PROT_READ | PROT_WRITE);
729 EXPECT_EQ(vmas[2].flags, PROT_READ | PROT_WRITE);
730 EXPECT_EQ(vmas[3].flags, PROT_READ | PROT_EXEC);
731 EXPECT_EQ(vmas[4].flags, PROT_READ | PROT_EXEC);
732 EXPECT_EQ(vmas[5].flags, PROT_READ | PROT_EXEC);
733
734 // Check Shared
735 EXPECT_FALSE(vmas[0].is_shared);
736 EXPECT_FALSE(vmas[1].is_shared);
737 EXPECT_FALSE(vmas[2].is_shared);
738 EXPECT_FALSE(vmas[3].is_shared);
739 EXPECT_FALSE(vmas[4].is_shared);
740 EXPECT_FALSE(vmas[5].is_shared);
741
742 // Check Offset
743 EXPECT_EQ(vmas[0].offset, 0x0);
744 EXPECT_EQ(vmas[1].offset, 0x0);
745 EXPECT_EQ(vmas[2].offset, 0x0);
746 EXPECT_EQ(vmas[3].offset, 0x00016000);
747 EXPECT_EQ(vmas[4].offset, 0x001ee000);
748 EXPECT_EQ(vmas[5].offset, 0x0);
749
750 // Check Inode
751 EXPECT_EQ(vmas[0].inode, 0);
752 EXPECT_EQ(vmas[1].inode, 3165);
753 EXPECT_EQ(vmas[2].inode, 0);
754 EXPECT_EQ(vmas[3].inode, 1947);
755 EXPECT_EQ(vmas[4].inode, 1537);
756 EXPECT_EQ(vmas[5].inode, 0);
757 }
758
TEST(ProcMemInfo,SmapsReturnTest)759 TEST(ProcMemInfo, SmapsReturnTest) {
760 // Make sure Smaps() is never empty for any process
761 ProcMemInfo proc_mem(pid);
762 auto vmas = proc_mem.Smaps();
763 EXPECT_FALSE(vmas.empty());
764 }
765
TEST(ProcMemInfo,SmapsTest)766 TEST(ProcMemInfo, SmapsTest) {
767 std::string exec_dir = ::android::base::GetExecutableDirectory();
768 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
769 ProcMemInfo proc_mem(pid);
770 auto vmas = proc_mem.Smaps(path);
771
772 ASSERT_FALSE(vmas.empty());
773 #ifndef __x86_64__
774 // We should get a total of 6 vmas
775 ASSERT_EQ(vmas.size(), 6);
776 #else
777 // We should get a total of 5 vmas ([vsyscall] is excluded)
778 ASSERT_EQ(vmas.size(), 5);
779 #endif
780
781 // Expect values to be equal to what we have in testdata1/smaps_short
782 // Check for sizes first
783 ASSERT_EQ(vmas[0].usage.vss, 32768);
784 EXPECT_EQ(vmas[1].usage.vss, 11204);
785 EXPECT_EQ(vmas[2].usage.vss, 16896);
786 EXPECT_EQ(vmas[3].usage.vss, 260);
787 EXPECT_EQ(vmas[4].usage.vss, 6060);
788 #ifndef __x86_64__
789 EXPECT_EQ(vmas[5].usage.vss, 4);
790 #endif
791
792 // Check for names
793 EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
794 EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
795 EXPECT_TRUE(vmas[2].name == "[anon:libc_malloc]" ||
796 android::base::StartsWith(vmas[2].name, "[anon:scudo:"))
797 << "Unknown map name " << vmas[2].name;
798 EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
799 EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
800 #ifndef __x86_64__
801 EXPECT_EQ(vmas[5].name, "[vsyscall]");
802 #endif
803
804 EXPECT_EQ(vmas[0].usage.rss, 2048);
805 EXPECT_EQ(vmas[1].usage.rss, 11188);
806 EXPECT_EQ(vmas[2].usage.rss, 15272);
807 EXPECT_EQ(vmas[3].usage.rss, 260);
808 EXPECT_EQ(vmas[4].usage.rss, 4132);
809 #ifndef __x86_64__
810 EXPECT_EQ(vmas[5].usage.rss, 0);
811 #endif
812
813 EXPECT_EQ(vmas[0].usage.pss, 113);
814 EXPECT_EQ(vmas[1].usage.pss, 2200);
815 EXPECT_EQ(vmas[2].usage.pss, 15272);
816 EXPECT_EQ(vmas[3].usage.pss, 260);
817 EXPECT_EQ(vmas[4].usage.pss, 1274);
818 #ifndef __x86_64__
819 EXPECT_EQ(vmas[5].usage.pss, 0);
820 #endif
821
822 EXPECT_EQ(vmas[0].usage.uss, 0);
823 EXPECT_EQ(vmas[1].usage.uss, 1660);
824 EXPECT_EQ(vmas[2].usage.uss, 15272);
825 EXPECT_EQ(vmas[3].usage.uss, 260);
826 EXPECT_EQ(vmas[4].usage.uss, 0);
827 #ifndef __x86_64__
828 EXPECT_EQ(vmas[5].usage.uss, 0);
829 #endif
830
831 EXPECT_EQ(vmas[0].usage.private_clean, 0);
832 EXPECT_EQ(vmas[1].usage.private_clean, 0);
833 EXPECT_EQ(vmas[2].usage.private_clean, 0);
834 EXPECT_EQ(vmas[3].usage.private_clean, 260);
835 EXPECT_EQ(vmas[4].usage.private_clean, 0);
836 #ifndef __x86_64__
837 EXPECT_EQ(vmas[5].usage.private_clean, 0);
838 #endif
839
840 EXPECT_EQ(vmas[0].usage.private_dirty, 0);
841 EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
842 EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
843 EXPECT_EQ(vmas[3].usage.private_dirty, 0);
844 EXPECT_EQ(vmas[4].usage.private_dirty, 0);
845 #ifndef __x86_64__
846 EXPECT_EQ(vmas[5].usage.private_dirty, 0);
847 #endif
848
849 EXPECT_EQ(vmas[0].usage.shared_clean, 0);
850 EXPECT_EQ(vmas[1].usage.shared_clean, 80);
851 EXPECT_EQ(vmas[2].usage.shared_clean, 0);
852 EXPECT_EQ(vmas[3].usage.shared_clean, 0);
853 EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
854 #ifndef __x86_64__
855 EXPECT_EQ(vmas[5].usage.shared_clean, 0);
856 #endif
857
858 EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
859 EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
860 EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
861 EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
862 EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
863 #ifndef __x86_64__
864 EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
865 #endif
866
867 EXPECT_EQ(vmas[0].usage.swap, 0);
868 EXPECT_EQ(vmas[1].usage.swap, 0);
869 EXPECT_EQ(vmas[2].usage.swap, 0);
870 EXPECT_EQ(vmas[3].usage.swap, 0);
871 EXPECT_EQ(vmas[4].usage.swap, 0);
872 #ifndef __x86_64__
873 EXPECT_EQ(vmas[5].usage.swap, 0);
874 #endif
875
876 EXPECT_EQ(vmas[0].usage.swap_pss, 0);
877 EXPECT_EQ(vmas[1].usage.swap_pss, 0);
878 EXPECT_EQ(vmas[2].usage.swap_pss, 0);
879 EXPECT_EQ(vmas[3].usage.swap_pss, 0);
880 EXPECT_EQ(vmas[4].usage.swap_pss, 0);
881 #ifndef __x86_64__
882 EXPECT_EQ(vmas[5].usage.swap_pss, 0);
883 #endif
884 }
885
TEST(ProcMemInfo,SmapsPopulatesUsageTest)886 TEST(ProcMemInfo, SmapsPopulatesUsageTest) {
887 std::string exec_dir = ::android::base::GetExecutableDirectory();
888 std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
889 ProcMemInfo proc_mem(pid);
890 auto vmas = proc_mem.Smaps(path, true);
891
892 // Expect values to be equal to sums of usage in testdata1/smaps_short. For
893 // this data, only vss differs on x86.
894 #ifndef __x86_64__
895 EXPECT_EQ(proc_mem.Usage().vss, 67192);
896 #else
897 EXPECT_EQ(proc_mem.Usage().vss, 67188);
898 #endif
899 EXPECT_EQ(proc_mem.Usage().rss, 32900);
900 EXPECT_EQ(proc_mem.Usage().pss, 19119);
901 EXPECT_EQ(proc_mem.Usage().uss, 17192);
902 EXPECT_EQ(proc_mem.Usage().private_clean, 260);
903 EXPECT_EQ(proc_mem.Usage().private_dirty, 16932);
904 EXPECT_EQ(proc_mem.Usage().shared_clean, 4212);
905 EXPECT_EQ(proc_mem.Usage().shared_dirty, 11496);
906 EXPECT_EQ(proc_mem.Usage().swap, 0);
907 EXPECT_EQ(proc_mem.Usage().swap_pss, 0);
908 }
909
TEST(SysMemInfo,TestSysMemInfoFile)910 TEST(SysMemInfo, TestSysMemInfoFile) {
911 std::string meminfo = R"meminfo(MemTotal: 3019740 kB
912 MemFree: 1809728 kB
913 MemAvailable: 2546560 kB
914 Buffers: 54736 kB
915 Cached: 776052 kB
916 SwapCached: 0 kB
917 Active: 445856 kB
918 Inactive: 459092 kB
919 Active(anon): 78492 kB
920 Inactive(anon): 2240 kB
921 Active(file): 367364 kB
922 Inactive(file): 456852 kB
923 Unevictable: 3096 kB
924 Mlocked: 3096 kB
925 SwapTotal: 32768 kB
926 SwapFree: 4096 kB
927 Dirty: 32 kB
928 Writeback: 0 kB
929 AnonPages: 74988 kB
930 Mapped: 62624 kB
931 Shmem: 4020 kB
932 KReclaimable: 87324 kB
933 Slab: 86464 kB
934 SReclaimable: 44432 kB
935 SUnreclaim: 42032 kB
936 KernelStack: 4880 kB
937 PageTables: 2900 kB
938 NFS_Unstable: 0 kB
939 Bounce: 0 kB
940 WritebackTmp: 0 kB
941 CommitLimit: 1509868 kB
942 Committed_AS: 80296 kB
943 VmallocTotal: 263061440 kB
944 VmallocUsed: 65536 kB
945 VmallocChunk: 0 kB
946 AnonHugePages: 6144 kB
947 ShmemHugePages: 0 kB
948 ShmemPmdMapped: 0 kB
949 CmaTotal: 131072 kB
950 CmaFree: 130380 kB
951 HugePages_Total: 0
952 HugePages_Free: 0
953 HugePages_Rsvd: 0
954 HugePages_Surp: 0
955 Hugepagesize: 2048 kB)meminfo";
956
957 TemporaryFile tf;
958 ASSERT_TRUE(tf.fd != -1);
959 ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
960
961 SysMemInfo mi;
962 ASSERT_TRUE(mi.ReadMemInfo(tf.path));
963 EXPECT_EQ(mi.mem_total_kb(), 3019740);
964 EXPECT_EQ(mi.mem_free_kb(), 1809728);
965 EXPECT_EQ(mi.mem_buffers_kb(), 54736);
966 EXPECT_EQ(mi.mem_cached_kb(), 776052);
967 EXPECT_EQ(mi.mem_shmem_kb(), 4020);
968 EXPECT_EQ(mi.mem_slab_kb(), 86464);
969 EXPECT_EQ(mi.mem_slab_reclaimable_kb(), 44432);
970 EXPECT_EQ(mi.mem_slab_unreclaimable_kb(), 42032);
971 EXPECT_EQ(mi.mem_swap_kb(), 32768);
972 EXPECT_EQ(mi.mem_swap_free_kb(), 4096);
973 EXPECT_EQ(mi.mem_mapped_kb(), 62624);
974 EXPECT_EQ(mi.mem_vmalloc_used_kb(), 65536);
975 EXPECT_EQ(mi.mem_page_tables_kb(), 2900);
976 EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
977 EXPECT_EQ(mi.mem_kreclaimable_kb(), 87324);
978 EXPECT_EQ(mi.mem_active_kb(), 445856);
979 EXPECT_EQ(mi.mem_inactive_kb(), 459092);
980 EXPECT_EQ(mi.mem_unevictable_kb(), 3096);
981 EXPECT_EQ(mi.mem_available_kb(), 2546560);
982 EXPECT_EQ(mi.mem_active_anon_kb(), 78492);
983 EXPECT_EQ(mi.mem_inactive_anon_kb(), 2240);
984 EXPECT_EQ(mi.mem_active_file_kb(), 367364);
985 EXPECT_EQ(mi.mem_inactive_file_kb(), 456852);
986 EXPECT_EQ(mi.mem_cma_total_kb(), 131072);
987 EXPECT_EQ(mi.mem_cma_free_kb(), 130380);
988 }
989
TEST(SysMemInfo,TestEmptyFile)990 TEST(SysMemInfo, TestEmptyFile) {
991 TemporaryFile tf;
992 std::string empty_string = "";
993 ASSERT_TRUE(tf.fd != -1);
994 ASSERT_TRUE(::android::base::WriteStringToFd(empty_string, tf.fd));
995
996 SysMemInfo mi;
997 EXPECT_TRUE(mi.ReadMemInfo(tf.path));
998 EXPECT_EQ(mi.mem_total_kb(), 0);
999 }
1000
TEST(SysMemInfo,TestZramTotal)1001 TEST(SysMemInfo, TestZramTotal) {
1002 std::string exec_dir = ::android::base::GetExecutableDirectory();
1003
1004 SysMemInfo mi;
1005 std::string zram_mmstat_dir = exec_dir + "/testdata1/";
1006 EXPECT_EQ(mi.mem_zram_kb(zram_mmstat_dir.c_str()), 30504);
1007
1008 std::string zram_memused_dir = exec_dir + "/testdata2/";
1009 EXPECT_EQ(mi.mem_zram_kb(zram_memused_dir.c_str()), 30504);
1010 }
1011
1012 enum {
1013 MEMINFO_TOTAL,
1014 MEMINFO_FREE,
1015 MEMINFO_BUFFERS,
1016 MEMINFO_CACHED,
1017 MEMINFO_SHMEM,
1018 MEMINFO_SLAB,
1019 MEMINFO_SLAB_RECLAIMABLE,
1020 MEMINFO_SLAB_UNRECLAIMABLE,
1021 MEMINFO_SWAP_TOTAL,
1022 MEMINFO_SWAP_FREE,
1023 MEMINFO_ZRAM_TOTAL,
1024 MEMINFO_MAPPED,
1025 MEMINFO_VMALLOC_USED,
1026 MEMINFO_PAGE_TABLES,
1027 MEMINFO_KERNEL_STACK,
1028 MEMINFO_KRECLAIMABLE,
1029 MEMINFO_ACTIVE,
1030 MEMINFO_INACTIVE,
1031 MEMINFO_UNEVICTABLE,
1032 MEMINFO_AVAILABLE,
1033 MEMINFO_ACTIVE_ANON,
1034 MEMINFO_INACTIVE_ANON,
1035 MEMINFO_ACTIVE_FILE,
1036 MEMINFO_INACTIVE_FILE,
1037 MEMINFO_CMA_TOTAL,
1038 MEMINFO_CMA_FREE,
1039 MEMINFO_COUNT
1040 };
1041
TEST(SysMemInfo,TestZramWithTags)1042 TEST(SysMemInfo, TestZramWithTags) {
1043 std::string meminfo = R"meminfo(MemTotal: 3019740 kB
1044 MemFree: 1809728 kB
1045 MemAvailable: 2546560 kB
1046 Buffers: 54736 kB
1047 Cached: 776052 kB
1048 SwapCached: 0 kB
1049 Active: 445856 kB
1050 Inactive: 459092 kB
1051 Active(anon): 78492 kB
1052 Inactive(anon): 2240 kB
1053 Active(file): 367364 kB
1054 Inactive(file): 456852 kB
1055 Unevictable: 3096 kB
1056 Mlocked: 3096 kB
1057 SwapTotal: 32768 kB
1058 SwapFree: 4096 kB
1059 Dirty: 32 kB
1060 Writeback: 0 kB
1061 AnonPages: 74988 kB
1062 Mapped: 62624 kB
1063 Shmem: 4020 kB
1064 KReclaimable: 87324 kB
1065 Slab: 86464 kB
1066 SReclaimable: 44432 kB
1067 SUnreclaim: 42032 kB
1068 KernelStack: 4880 kB
1069 PageTables: 2900 kB
1070 NFS_Unstable: 0 kB
1071 Bounce: 0 kB
1072 WritebackTmp: 0 kB
1073 CommitLimit: 1509868 kB
1074 Committed_AS: 80296 kB
1075 VmallocTotal: 263061440 kB
1076 VmallocUsed: 65536 kB
1077 VmallocChunk: 0 kB
1078 AnonHugePages: 6144 kB
1079 ShmemHugePages: 0 kB
1080 ShmemPmdMapped: 0 kB
1081 CmaTotal: 131072 kB
1082 CmaFree: 130380 kB
1083 HugePages_Total: 0
1084 HugePages_Free: 0
1085 HugePages_Rsvd: 0
1086 HugePages_Surp: 0
1087 Hugepagesize: 2048 kB)meminfo";
1088
1089 TemporaryFile tf;
1090 ASSERT_TRUE(tf.fd != -1);
1091 ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
1092 std::string file = std::string(tf.path);
1093 std::vector<uint64_t> mem;
1094 std::vector<std::string_view> tags(SysMemInfo::kDefaultSysMemInfoTags.begin(),
1095 SysMemInfo::kDefaultSysMemInfoTags.end());
1096 auto it = tags.begin();
1097 tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
1098 SysMemInfo mi;
1099
1100 // Read system memory info
1101 mem.resize(tags.size());
1102 EXPECT_TRUE(mi.ReadMemInfo(tags.size(), tags.data(), mem.data(), file.c_str()));
1103 EXPECT_EQ(mem[MEMINFO_TOTAL], 3019740);
1104 EXPECT_EQ(mem[MEMINFO_FREE], 1809728);
1105 EXPECT_EQ(mem[MEMINFO_BUFFERS], 54736);
1106 EXPECT_EQ(mem[MEMINFO_CACHED], 776052);
1107 EXPECT_EQ(mem[MEMINFO_SHMEM], 4020);
1108 EXPECT_EQ(mem[MEMINFO_SLAB], 86464);
1109 EXPECT_EQ(mem[MEMINFO_SLAB_RECLAIMABLE], 44432);
1110 EXPECT_EQ(mem[MEMINFO_SLAB_UNRECLAIMABLE], 42032);
1111 EXPECT_EQ(mem[MEMINFO_SWAP_TOTAL], 32768);
1112 EXPECT_EQ(mem[MEMINFO_SWAP_FREE], 4096);
1113 EXPECT_EQ(mem[MEMINFO_MAPPED], 62624);
1114 EXPECT_EQ(mem[MEMINFO_VMALLOC_USED], 65536);
1115 EXPECT_EQ(mem[MEMINFO_PAGE_TABLES], 2900);
1116 EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
1117 EXPECT_EQ(mem[MEMINFO_KRECLAIMABLE], 87324);
1118 EXPECT_EQ(mem[MEMINFO_ACTIVE], 445856);
1119 EXPECT_EQ(mem[MEMINFO_INACTIVE], 459092);
1120 EXPECT_EQ(mem[MEMINFO_UNEVICTABLE], 3096);
1121 EXPECT_EQ(mem[MEMINFO_AVAILABLE], 2546560);
1122 EXPECT_EQ(mem[MEMINFO_ACTIVE_ANON], 78492);
1123 EXPECT_EQ(mem[MEMINFO_INACTIVE_ANON], 2240);
1124 EXPECT_EQ(mem[MEMINFO_ACTIVE_FILE], 367364);
1125 EXPECT_EQ(mem[MEMINFO_INACTIVE_FILE], 456852);
1126 EXPECT_EQ(mem[MEMINFO_CMA_TOTAL], 131072);
1127 EXPECT_EQ(mem[MEMINFO_CMA_FREE], 130380);
1128 }
1129
TEST(SysMemInfo,TestVmallocInfoNoMemory)1130 TEST(SysMemInfo, TestVmallocInfoNoMemory) {
1131 std::string vmallocinfo =
1132 R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
1133 0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
1134 0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
1135 0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap)vmallocinfo";
1136
1137 TemporaryFile tf;
1138 ASSERT_TRUE(tf.fd != -1);
1139 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
1140 std::string file = std::string(tf.path);
1141
1142 EXPECT_EQ(ReadVmallocInfo(file.c_str()), 0);
1143 }
1144
TEST(SysMemInfo,TestVmallocInfoKernel)1145 TEST(SysMemInfo, TestVmallocInfoKernel) {
1146 std::string vmallocinfo =
1147 R"vmallocinfo(0x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc)vmallocinfo";
1148
1149 TemporaryFile tf;
1150 ASSERT_TRUE(tf.fd != -1);
1151 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
1152 std::string file = std::string(tf.path);
1153
1154 EXPECT_EQ(ReadVmallocInfo(file.c_str()), getpagesize());
1155 }
1156
TEST(SysMemInfo,TestVmallocInfoModule)1157 TEST(SysMemInfo, TestVmallocInfoModule) {
1158 std::string vmallocinfo =
1159 R"vmallocinfo(0x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
1160
1161 TemporaryFile tf;
1162 ASSERT_TRUE(tf.fd != -1);
1163 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
1164 std::string file = std::string(tf.path);
1165
1166 EXPECT_EQ(ReadVmallocInfo(file.c_str()), 6 * getpagesize());
1167 }
1168
TEST(SysMemInfo,TestVmallocInfoAll)1169 TEST(SysMemInfo, TestVmallocInfoAll) {
1170 std::string vmallocinfo =
1171 R"vmallocinfo(0x0000000000000000-0x0000000000000000 69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap
1172 0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=b220000 ioremap
1173 0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
1174 0x0000000000000000-0x0000000000000000 8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap
1175 0x0000000000000000-0x0000000000000000 8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc
1176 0x0000000000000000-0x0000000000000000 28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
1177
1178 TemporaryFile tf;
1179 ASSERT_TRUE(tf.fd != -1);
1180 ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
1181 std::string file = std::string(tf.path);
1182
1183 EXPECT_EQ(ReadVmallocInfo(file.c_str()), 7 * getpagesize());
1184 }
1185
TEST(SysMemInfo,TestReadIonHeapsSizeKb)1186 TEST(SysMemInfo, TestReadIonHeapsSizeKb) {
1187 std::string total_heaps_kb = R"total_heaps_kb(98480)total_heaps_kb";
1188 uint64_t size;
1189
1190 TemporaryFile tf;
1191 ASSERT_TRUE(tf.fd != -1);
1192 ASSERT_TRUE(::android::base::WriteStringToFd(total_heaps_kb, tf.fd));
1193 std::string file = std::string(tf.path);
1194
1195 ASSERT_TRUE(ReadIonHeapsSizeKb(&size, file));
1196 EXPECT_EQ(size, 98480);
1197 }
1198
TEST(SysMemInfo,TestReadIonPoolsSizeKb)1199 TEST(SysMemInfo, TestReadIonPoolsSizeKb) {
1200 std::string total_pools_kb = R"total_pools_kb(416)total_pools_kb";
1201 uint64_t size;
1202
1203 TemporaryFile tf;
1204 ASSERT_TRUE(tf.fd != -1);
1205 ASSERT_TRUE(::android::base::WriteStringToFd(total_pools_kb, tf.fd));
1206 std::string file = std::string(tf.path);
1207
1208 ASSERT_TRUE(ReadIonPoolsSizeKb(&size, file));
1209 EXPECT_EQ(size, 416);
1210 }
1211
TEST(SysMemInfo,TestReadGpuTotalUsageKb)1212 TEST(SysMemInfo, TestReadGpuTotalUsageKb) {
1213 uint64_t size;
1214
1215 if (android::base::GetIntProperty("ro.vendor.api_level", 0) < __ANDROID_API_S__) {
1216 GTEST_SKIP();
1217 }
1218
1219 KernelVersion min_kernel_version = KernelVersion(5, 4, 0);
1220 KernelVersion kernel_version = VintfObject::GetInstance()
1221 ->getRuntimeInfo(RuntimeInfo::FetchFlag::CPU_VERSION)
1222 ->kernelVersion();
1223 if (kernel_version < min_kernel_version) {
1224 GTEST_SKIP();
1225 }
1226
1227 ASSERT_TRUE(ReadGpuTotalUsageKb(&size));
1228 EXPECT_TRUE(size >= 0);
1229 }
1230
TEST(AndroidProcHeaps,ExtractAndroidHeapStatsFromFileTest)1231 TEST(AndroidProcHeaps, ExtractAndroidHeapStatsFromFileTest) {
1232 std::string smaps =
1233 R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
1234 Name: [anon:dalvik-main space (region space)]
1235 Size: 8448 kB
1236 KernelPageSize: 4 kB
1237 MMUPageSize: 4 kB
1238 Rss: 2652 kB
1239 Pss: 2652 kB
1240 Shared_Clean: 840 kB
1241 Shared_Dirty: 40 kB
1242 Private_Clean: 84 kB
1243 Private_Dirty: 2652 kB
1244 Referenced: 2652 kB
1245 Anonymous: 2652 kB
1246 AnonHugePages: 0 kB
1247 ShmemPmdMapped: 0 kB
1248 Shared_Hugetlb: 0 kB
1249 Private_Hugetlb: 0 kB
1250 Swap: 102 kB
1251 SwapPss: 70 kB
1252 Locked: 2652 kB
1253 VmFlags: rd wr mr mw me ac
1254 )smaps";
1255
1256 TemporaryFile tf;
1257 ASSERT_TRUE(tf.fd != -1);
1258 ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
1259
1260 bool foundSwapPss;
1261 AndroidHeapStats stats[_NUM_HEAP];
1262 ASSERT_TRUE(ExtractAndroidHeapStatsFromFile(tf.path, stats, &foundSwapPss));
1263
1264 AndroidHeapStats actualStats;
1265 for (int i = 0; i < _NUM_CORE_HEAP; i++) {
1266 actualStats.pss += stats[i].pss;
1267 actualStats.swappablePss += stats[i].swappablePss;
1268 actualStats.rss += stats[i].rss;
1269 actualStats.privateDirty += stats[i].privateDirty;
1270 actualStats.sharedDirty += stats[i].sharedDirty;
1271 actualStats.privateClean += stats[i].privateClean;
1272 actualStats.sharedClean += stats[i].sharedClean;
1273 actualStats.swappedOut += stats[i].swappedOut;
1274 actualStats.swappedOutPss += stats[i].swappedOutPss;
1275 }
1276 EXPECT_EQ(actualStats.pss, 2652);
1277 EXPECT_EQ(actualStats.swappablePss, 0);
1278 EXPECT_EQ(actualStats.rss, 2652);
1279 EXPECT_EQ(actualStats.privateDirty, 2652);
1280 EXPECT_EQ(actualStats.sharedDirty, 40);
1281 EXPECT_EQ(actualStats.privateClean, 84);
1282 EXPECT_EQ(actualStats.sharedClean, 840);
1283 EXPECT_EQ(actualStats.swappedOut, 102);
1284 EXPECT_EQ(actualStats.swappedOutPss, 70);
1285 }
1286
1287 class DmabufHeapStats : public ::testing::Test {
1288 public:
SetUp()1289 virtual void SetUp() {
1290 fs::current_path(fs::temp_directory_path());
1291 buffer_stats_path = fs::current_path() / "buffers";
1292 ASSERT_TRUE(fs::create_directory(buffer_stats_path));
1293 heap_root_path = fs::current_path() / "dma_heap";
1294 ASSERT_TRUE(fs::create_directory(heap_root_path));
1295 }
TearDown()1296 virtual void TearDown() {
1297 fs::remove_all(buffer_stats_path);
1298 fs::remove_all(heap_root_path);
1299 }
1300
1301 fs::path buffer_stats_path;
1302 fs::path heap_root_path;
1303 };
1304
TEST_F(DmabufHeapStats,TestDmabufHeapTotalExportedKb)1305 TEST_F(DmabufHeapStats, TestDmabufHeapTotalExportedKb) {
1306 using android::base::StringPrintf;
1307 uint64_t size;
1308
1309 auto system_heap_path = heap_root_path / "system";
1310 ASSERT_TRUE(android::base::WriteStringToFile("test", system_heap_path));
1311
1312 for (unsigned int inode_number = 74831; inode_number < 74841; inode_number++) {
1313 auto buffer_path = buffer_stats_path / StringPrintf("%u", inode_number);
1314 ASSERT_TRUE(fs::create_directories(buffer_path));
1315
1316 auto buffer_size_path = buffer_path / "size";
1317 const std::string buffer_size = "4096";
1318 ASSERT_TRUE(android::base::WriteStringToFile(buffer_size, buffer_size_path));
1319
1320 auto exp_name_path = buffer_path / "exporter_name";
1321 const std::string exp_name = inode_number % 2 ? "system" : "other";
1322 ASSERT_TRUE(android::base::WriteStringToFile(exp_name, exp_name_path));
1323 }
1324
1325 ASSERT_TRUE(ReadDmabufHeapTotalExportedKb(&size, heap_root_path, buffer_stats_path));
1326 ASSERT_EQ(size, 20);
1327 }
1328
TEST(SysMemInfo,TestReadDmaBufHeapPoolsSizeKb)1329 TEST(SysMemInfo, TestReadDmaBufHeapPoolsSizeKb) {
1330 std::string total_pools_kb = R"total_pools_kb(416)total_pools_kb";
1331 uint64_t size;
1332
1333 TemporaryFile tf;
1334 ASSERT_TRUE(tf.fd != -1);
1335 ASSERT_TRUE(::android::base::WriteStringToFd(total_pools_kb, tf.fd));
1336 std::string file = std::string(tf.path);
1337
1338 ASSERT_TRUE(ReadDmabufHeapPoolsSizeKb(&size, file));
1339 EXPECT_EQ(size, 416);
1340 }
1341
main(int argc,char ** argv)1342 int main(int argc, char** argv) {
1343 ::testing::InitGoogleTest(&argc, argv);
1344 ::android::base::InitLogging(argv, android::base::StderrLogger);
1345 pid = getpid();
1346 return RUN_ALL_TESTS();
1347 }
1348