Update ProcMemInfo to report usage in KB

This change modifies ReadVmaStats() to report usage in KB instead of B.
This is intended to keep memory units consistent between Smaps() and
Maps(). Existing tools that call methods that use Maps() (procrank,
librank, procmem, wsstop) have been updated to reflect this.

A default KB-to-B conversion has been added to FillInVmaStats() (which
calls ReadVmaStats()), because most callers of this function expect
usage to be reported in bytes.

Bug: 236427386
Test: - atest libmeminfo_test
      - manually checked before/after output of the modified tools.
Change-Id: I036082d0e2d7a3869212e9ef0decf6ab030a69fa
diff --git a/include/meminfo/procmeminfo.h b/include/meminfo/procmeminfo.h
index 4b1bc5e..ac9d85d 100644
--- a/include/meminfo/procmeminfo.h
+++ b/include/meminfo/procmeminfo.h
@@ -50,8 +50,9 @@
     const std::vector<Vma>& MapsWithoutUsageStats();
 
     // If MapsWithoutUsageStats was called, this function will fill in
-    // usage stats for this single vma.
-    bool FillInVmaStats(Vma& vma);
+    // usage stats for this single vma. If 'use_kb' is true, the vma's
+    // usage will be populated in kilobytes instead of bytes.
+    bool FillInVmaStats(Vma& vma, bool use_kb = false);
 
     // If ReadMaps (with get_usage_stats == false) or MapsWithoutUsageStats was
     // called, this function will fill in usage stats for all vmas in 'maps_'.
diff --git a/libsmapinfo/smapinfo.cpp b/libsmapinfo/smapinfo.cpp
index 94212dd..87a2976 100644
--- a/libsmapinfo/smapinfo.cpp
+++ b/libsmapinfo/smapinfo.cpp
@@ -102,6 +102,10 @@
             unique_swap_ += swap_offset_array[off] == 1 ? getpagesize() : 0;
             zswap_ = proportional_swap_ * zram_compression_ratio;
         }
+        // This is divided by 1024 to convert to KB.
+        proportional_swap_ /= 1024;
+        unique_swap_ /= 1024;
+        zswap_ /= 1024;
     }
 
     // Getters
@@ -310,20 +314,18 @@
 
     if (params->show_wss) {
         out << StringPrintf("%6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ",
-                            proc.Usage(params->show_wss).rss / 1024,
-                            proc.Usage(params->show_wss).pss / 1024,
-                            proc.Usage(params->show_wss).uss / 1024);
+                            proc.Usage(params->show_wss).rss, proc.Usage(params->show_wss).pss,
+                            proc.Usage(params->show_wss).uss);
     } else {
-        out << StringPrintf(
-                "%7" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ",
-                proc.Usage(params->show_wss).vss / 1024, proc.Usage(params->show_wss).rss / 1024,
-                proc.Usage(params->show_wss).pss / 1024, proc.Usage(params->show_wss).uss / 1024);
+        out << StringPrintf("%7" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ",
+                            proc.Usage(params->show_wss).vss, proc.Usage(params->show_wss).rss,
+                            proc.Usage(params->show_wss).pss, proc.Usage(params->show_wss).uss);
         if (params->swap_enabled) {
-            out << StringPrintf("%6" PRIu64 "K  ", proc.Usage(params->show_wss).swap / 1024);
-            out << StringPrintf("%6" PRIu64 "K  ", proc.proportional_swap() / 1024);
-            out << StringPrintf("%6" PRIu64 "K  ", proc.unique_swap() / 1024);
+            out << StringPrintf("%6" PRIu64 "K  ", proc.Usage(params->show_wss).swap);
+            out << StringPrintf("%6" PRIu64 "K  ", proc.proportional_swap());
+            out << StringPrintf("%6" PRIu64 "K  ", proc.unique_swap());
             if (params->zram_enabled) {
-                out << StringPrintf("%6" PRIu64 "K  ", (proc.zswap() / 1024));
+                out << StringPrintf("%6" PRIu64 "K  ", (proc.zswap()));
             }
         }
     }
@@ -337,17 +339,17 @@
     }
 
     if (params->show_wss) {
-        out << StringPrintf("%7s  %6" PRIu64 "K  %6" PRIu64 "K  ", "", params->total_pss / 1024,
-                            params->total_uss / 1024);
+        out << StringPrintf("%7s  %6" PRIu64 "K  %6" PRIu64 "K  ", "", params->total_pss,
+                            params->total_uss);
     } else {
-        out << StringPrintf("%8s  %7s  %6" PRIu64 "K  %6" PRIu64 "K  ", "", "",
-                            params->total_pss / 1024, params->total_uss / 1024);
+        out << StringPrintf("%8s  %7s  %6" PRIu64 "K  %6" PRIu64 "K  ", "", "", params->total_pss,
+                            params->total_uss);
         if (params->swap_enabled) {
-            out << StringPrintf("%6" PRIu64 "K  ", params->total_swap / 1024);
-            out << StringPrintf("%6" PRIu64 "K  ", params->total_pswap / 1024);
-            out << StringPrintf("%6" PRIu64 "K  ", params->total_uswap / 1024);
+            out << StringPrintf("%6" PRIu64 "K  ", params->total_swap);
+            out << StringPrintf("%6" PRIu64 "K  ", params->total_pswap);
+            out << StringPrintf("%6" PRIu64 "K  ", params->total_uswap);
             if (params->zram_enabled) {
-                out << StringPrintf("%6" PRIu64 "K  ", params->total_zswap / 1024);
+                out << StringPrintf("%6" PRIu64 "K  ", params->total_zswap);
             }
         }
     }
diff --git a/procmeminfo.cpp b/procmeminfo.cpp
index 137f589..f75bb6b 100644
--- a/procmeminfo.cpp
+++ b/procmeminfo.cpp
@@ -66,6 +66,27 @@
     to->shared_dirty += from.shared_dirty;
 }
 
+// Converts MemUsage stats from KB to B in case usage is expected in bytes.
+static void convert_usage_kb_to_b(MemUsage& usage) {
+    // These stats are only populated if /proc/<pid>/smaps is read, so they are excluded:
+    // swap_pss, anon_huge_pages, shmem_pmdmapped, file_pmd_mapped, shared_hugetlb, private_hugetlb.
+    constexpr int conversion_factor = 1024;
+    usage.vss *= conversion_factor;
+    usage.rss *= conversion_factor;
+    usage.pss *= conversion_factor;
+    usage.uss *= conversion_factor;
+
+    usage.swap *= conversion_factor;
+
+    usage.private_clean *= conversion_factor;
+    usage.private_dirty *= conversion_factor;
+
+    usage.shared_clean *= conversion_factor;
+    usage.shared_dirty *= conversion_factor;
+
+    usage.thp *= conversion_factor;
+}
+
 // Returns true if the line was valid smaps stats line false otherwise.
 static bool parse_smaps_field(const char* line, MemUsage* stats) {
     const char *end = line;
@@ -375,7 +396,7 @@
     return true;
 }
 
-bool ProcMemInfo::FillInVmaStats(Vma& vma) {
+bool ProcMemInfo::FillInVmaStats(Vma& vma, bool use_kb) {
     ::android::base::unique_fd pagemap_fd(GetPagemapFd(pid_));
     if (pagemap_fd == -1) {
         return false;
@@ -386,6 +407,9 @@
                    << vma.end << "]";
         return false;
     }
+    if (!use_kb) {
+        convert_usage_kb_to_b(vma.usage);
+    }
     return true;
 }
 
@@ -397,9 +421,9 @@
         return false;
     }
 
-    uint64_t pagesz = getpagesize();
-    size_t num_pages = (vma.end - vma.start) / pagesz;
-    size_t first_page = vma.start / pagesz;
+    uint64_t pagesz_kb = getpagesize() / 1024;
+    size_t num_pages = (vma.end - vma.start) / (pagesz_kb * 1024);
+    size_t first_page = vma.start / (pagesz_kb * 1024);
 
     std::vector<uint64_t> page_cache;
     size_t cur_page_cache_index = 0;
@@ -437,7 +461,7 @@
         if (!PAGE_PRESENT(page_info) && !PAGE_SWAPPED(page_info)) continue;
 
         if (PAGE_SWAPPED(page_info)) {
-            vma.usage.swap += pagesz;
+            vma.usage.swap += pagesz_kb;
             swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(page_info));
             continue;
         }
@@ -454,7 +478,7 @@
         }
 
         if (KPAGEFLAG_THP(cur_page_flags)) {
-            vma.usage.thp += pagesz;
+            vma.usage.thp += pagesz_kb;
         }
 
         // skip unwanted pages from the count
@@ -484,22 +508,22 @@
             // This effectively makes vss = rss for the working set is requested.
             // The libpagemap implementation returns vss > rss for
             // working set, which doesn't make sense.
-            vma.usage.vss += pagesz;
+            vma.usage.vss += pagesz_kb;
         }
 
-        vma.usage.rss += pagesz;
-        vma.usage.uss += is_private ? pagesz : 0;
-        vma.usage.pss += pagesz / cur_page_counts;
+        vma.usage.rss += pagesz_kb;
+        vma.usage.uss += is_private ? pagesz_kb : 0;
+        vma.usage.pss += pagesz_kb / cur_page_counts;
         if (is_private) {
-            vma.usage.private_dirty += is_dirty ? pagesz : 0;
-            vma.usage.private_clean += is_dirty ? 0 : pagesz;
+            vma.usage.private_dirty += is_dirty ? pagesz_kb : 0;
+            vma.usage.private_clean += is_dirty ? 0 : pagesz_kb;
         } else {
-            vma.usage.shared_dirty += is_dirty ? pagesz : 0;
-            vma.usage.shared_clean += is_dirty ? 0 : pagesz;
+            vma.usage.shared_dirty += is_dirty ? pagesz_kb : 0;
+            vma.usage.shared_clean += is_dirty ? 0 : pagesz_kb;
         }
     }
     if (!get_wss) {
-        vma.usage.vss += pagesz * num_pages;
+        vma.usage.vss += pagesz_kb * num_pages;
     }
     return true;
 }
diff --git a/tools/librank.cpp b/tools/librank.cpp
index 4321aed..2b5503f 100644
--- a/tools/librank.cpp
+++ b/tools/librank.cpp
@@ -240,16 +240,16 @@
     const MemUsage& usage = p.usage();
     // clang-format off
     output << EscapeCsvString(l.name())
-           << "," << l.pss() / 1024
+           << "," << l.pss()
            << "," << EscapeCsvString(p.cmdline())
            << ",\"[" << p.pid() << "]\""
-           << "," << usage.vss / 1024
-           << "," << usage.rss / 1024
-           << "," << usage.pss / 1024
-           << "," << usage.uss / 1024;
+           << "," << usage.vss
+           << "," << usage.rss
+           << "," << usage.pss
+           << "," << usage.uss;
     // clang-format on
     if (g_has_swap) {
-        output << "," << usage.swap / 1024;
+        output << "," << usage.swap;
     }
     output << "\n";
 }
@@ -258,16 +258,16 @@
     const MemUsage& usage = p.usage();
     // clang-format off
     output << "{\"Library\":" << EscapeJsonString(l.name())
-           << ",\"Total_RSS\":" << l.pss() / 1024
+           << ",\"Total_RSS\":" << l.pss()
            << ",\"Process\":" << EscapeJsonString(p.cmdline())
            << ",\"PID\":\"" << p.pid() << "\""
-           << ",\"VSS\":" << usage.vss / 1024
-           << ",\"RSS\":" << usage.rss / 1024
-           << ",\"PSS\":" << usage.pss / 1024
-           << ",\"USS\":" << usage.uss / 1024;
+           << ",\"VSS\":" << usage.vss
+           << ",\"RSS\":" << usage.rss
+           << ",\"PSS\":" << usage.pss
+           << ",\"USS\":" << usage.uss;
     // clang-format on
     if (g_has_swap) {
-        output << ",\"Swap\":" << usage.swap / 1024;
+        output << ",\"Swap\":" << usage.swap;
     }
     output << "}\n";
 }
@@ -397,7 +397,7 @@
     for (auto& lib : v_libs) {
         if (format == Format::RAW) {
             // clang-format off
-            std::cout << std::setw(6) << lib.pss() / 1024 << "K"
+            std::cout << std::setw(6) << lib.pss() << "K"
                       << std::setw(10) << ""
                       << std::setw(9) << ""
                       << std::setw(9) << ""
@@ -426,13 +426,13 @@
                 case Format::RAW:
                     // clang-format off
                     std::cout << std::setw(7) << ""
-                              << std::setw(9) << usage.vss / 1024 << "K  "
-                              << std::setw(6) << usage.rss / 1024 << "K  "
-                              << std::setw(6) << usage.pss / 1024 << "K  "
-                              << std::setw(6) << usage.uss / 1024 << "K  ";
+                              << std::setw(9) << usage.vss << "K  "
+                              << std::setw(6) << usage.rss << "K  "
+                              << std::setw(6) << usage.pss << "K  "
+                              << std::setw(6) << usage.uss << "K  ";
                     // clang-format on
                     if (g_has_swap) {
-                        std::cout << std::setw(6) << usage.swap / 1024 << "K  ";
+                        std::cout << std::setw(6) << usage.swap << "K  ";
                     }
                     std::cout << "  " << p.cmdline() << " [" << p.pid() << "]\n";
                     break;
diff --git a/tools/procmem.cpp b/tools/procmem.cpp
index 1fe8d50..619f490 100644
--- a/tools/procmem.cpp
+++ b/tools/procmem.cpp
@@ -85,15 +85,14 @@
 
 static void print_stats(std::stringstream& ss, const MemUsage& stats) {
     if (!show_wss) {
-        ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", stats.vss / 1024);
+        ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", stats.vss);
     }
 
     ss << ::android::base::StringPrintf(
             "%6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64
             "K  %6" PRIu64 "K  %6" PRIu64 "K ",
-            stats.rss / 1024, stats.pss / 1024, stats.uss / 1024, stats.shared_clean / 1024,
-            stats.shared_dirty / 1024, stats.private_clean / 1024, stats.private_dirty / 1024,
-            stats.thp / 1024);
+            stats.rss, stats.pss, stats.uss, stats.shared_clean, stats.shared_dirty,
+            stats.private_clean, stats.private_dirty, stats.thp);
 }
 
 static int show(const MemUsage& proc_stats, const std::vector<Vma>& maps) {
diff --git a/tools/wsstop.cpp b/tools/wsstop.cpp
index 368d04e..c0c6a86 100644
--- a/tools/wsstop.cpp
+++ b/tools/wsstop.cpp
@@ -69,9 +69,8 @@
     printf("%16" PRIx64 " %16" PRIx64 " ", v.start, v.end);
     printf("%8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64
            "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K ",
-           v.usage.vss / 1024, v.usage.rss / 1024, v.usage.pss / 1024, v.usage.shared_clean / 1024,
-           v.usage.shared_dirty / 1024, v.usage.private_clean / 1024, v.usage.private_dirty / 1024,
-           v.usage.swap / 1024, v.usage.swap_pss / 1024);
+           v.usage.vss, v.usage.rss, v.usage.pss, v.usage.shared_clean, v.usage.shared_dirty,
+           v.usage.private_clean, v.usage.private_dirty, v.usage.swap, v.usage.swap_pss);
     printf("%s\n", v.name.c_str());
 }