diff options
-rw-r--r-- | adb/client/commandline.cpp | 18 | ||||
-rwxr-xr-x | fs_mgr/fs_mgr.cpp | 22 | ||||
-rw-r--r-- | init/reboot_utils.cpp | 20 | ||||
-rw-r--r-- | libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h | 6 | ||||
-rw-r--r-- | libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp | 275 | ||||
-rw-r--r-- | libmeminfo/pageacct.cpp | 8 | ||||
-rw-r--r-- | libmeminfo/procmeminfo.cpp | 88 | ||||
-rw-r--r-- | libmeminfo/tools/procrank.cpp | 2 | ||||
-rw-r--r-- | libmeminfo/vts/AndroidTest.xml | 1 | ||||
-rw-r--r-- | lmkd/lmkd.c | 60 | ||||
-rw-r--r-- | rootdir/etc/ld.config.txt | 22 | ||||
-rw-r--r-- | rootdir/etc/ld.config.vndk_lite.txt | 1 | ||||
-rw-r--r-- | rootdir/init.rc | 4 | ||||
-rw-r--r-- | rootdir/update_and_install_ld_config.mk | 7 | ||||
-rw-r--r-- | usbd/usbd.cpp | 7 |
15 files changed, 378 insertions, 163 deletions
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp index e2a17c553..8dd85d7b0 100644 --- a/adb/client/commandline.cpp +++ b/adb/client/commandline.cpp @@ -1668,17 +1668,29 @@ int adb_commandline(int argc, const char** argv) { return 0; } } else if (!strcmp(argv[0], "rescue")) { + // adb rescue getprop // adb rescue getprop <prop> // adb rescue install <filename> // adb rescue wipe userdata - if (argc != 3) error_exit("rescue requires two arguments"); + if (argc < 2) error_exit("rescue requires at least one argument"); if (!strcmp(argv[1], "getprop")) { - return adb_connect_command(android::base::StringPrintf("rescue-getprop:%s", argv[2])); + if (argc == 2) { + return adb_connect_command("rescue-getprop:"); + } + if (argc == 3) { + return adb_connect_command( + android::base::StringPrintf("rescue-getprop:%s", argv[2])); + } + error_exit("invalid rescue getprop arguments"); } else if (!strcmp(argv[1], "install")) { + if (argc != 3) error_exit("rescue install requires two arguments"); if (adb_sideload_install(argv[2], true /* rescue_mode */) != 0) { return 1; } - } else if (!strcmp(argv[1], "wipe") && !strcmp(argv[2], "userdata")) { + } else if (!strcmp(argv[1], "wipe")) { + if (argc != 3 || strcmp(argv[2], "userdata") != 0) { + error_exit("invalid rescue wipe arguments"); + } return adb_wipe_devices(); } else { error_exit("invalid rescue argument"); diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 0eb44775e..6605df5e7 100755 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -245,11 +245,11 @@ static void check_fs(const std::string& blk_device, const std::string& fs_type, if (should_force_check(*fs_stat)) { ret = android_fork_execvp_ext( ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status, - true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0); + true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0); } else { ret = android_fork_execvp_ext( ARRAY_SIZE(e2fsck_argv), const_cast<char**>(e2fsck_argv), &status, true, - LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0); + LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0); } if (ret < 0) { @@ -263,13 +263,19 @@ static void check_fs(const std::string& blk_device, const std::string& fs_type, } } else if (is_f2fs(fs_type)) { const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN, "-a", blk_device.c_str()}; - LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device); + const char* f2fs_fsck_forced_argv[] = {F2FS_FSCK_BIN, "-f", blk_device.c_str()}; - ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), - const_cast<char **>(f2fs_fsck_argv), - &status, true, LOG_KLOG | LOG_FILE, - true, const_cast<char *>(FSCK_LOG_FILE), - NULL, 0); + if (should_force_check(*fs_stat)) { + LINFO << "Running " << F2FS_FSCK_BIN << " -f " << realpath(blk_device); + ret = android_fork_execvp_ext( + ARRAY_SIZE(f2fs_fsck_forced_argv), const_cast<char**>(f2fs_fsck_forced_argv), &status, + true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0); + } else { + LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device); + ret = android_fork_execvp_ext( + ARRAY_SIZE(f2fs_fsck_argv), const_cast<char**>(f2fs_fsck_argv), &status, true, + LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0); + } if (ret < 0) { /* No need to check for error in fork, we can't really handle it now */ LERROR << "Failed trying to run " << F2FS_FSCK_BIN; diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp index d1a712f2e..de085cc9b 100644 --- a/init/reboot_utils.cpp +++ b/init/reboot_utils.cpp @@ -21,11 +21,12 @@ #include <string> -#include "android-base/file.h" -#include "android-base/logging.h" -#include "android-base/strings.h" -#include "backtrace/Backtrace.h" -#include "cutils/android_reboot.h" +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/strings.h> +#include <backtrace/Backtrace.h> +#include <cutils/android_reboot.h> #include "capabilities.h" @@ -93,7 +94,14 @@ void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& break; case ANDROID_RB_THERMOFF: - reboot(RB_POWER_OFF); + if (android::base::GetBoolProperty("ro.thermal_warmreset", false)) { + LOG(INFO) << "Try to trigger a warm reset for thermal shutdown"; + static constexpr const char kThermalShutdownTarget[] = "shutdown,thermal"; + syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, kThermalShutdownTarget); + } else { + reboot(RB_POWER_OFF); + } break; } // In normal case, reboot should not return. diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h index a16c3fdaf..a6e7f6907 100644 --- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h +++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h @@ -19,6 +19,7 @@ #include <sys/types.h> #include <unistd.h> +#include <set> #include <string> #include <vector> #include <unordered_map> @@ -33,6 +34,7 @@ struct DmaBuffer { : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) { total_refs_ = 0; } + DmaBuffer() = default; ~DmaBuffer() = default; // Adds one file descriptor reference for the given pid @@ -54,11 +56,13 @@ struct DmaBuffer { ino_t inode() const { return inode_; } uint64_t total_refs() const { return total_refs_; } uint64_t count() const { return count_; }; + const std::set<pid_t>& pids() const { return pids_; } const std::string& name() const { return name_; } const std::string& exporter() const { return exporter_; } void SetName(const std::string& name) { name_ = name; } void SetExporter(const std::string& exporter) { exporter_ = exporter; } void SetCount(uint64_t count) { count_ = count; } + uint64_t Pss() const { return size_ / pids_.size(); } bool operator==(const DmaBuffer& rhs) { return (inode_ == rhs.inode()) && (size_ == rhs.size()) && (name_ == rhs.name()) && @@ -70,6 +74,7 @@ struct DmaBuffer { uint64_t size_; uint64_t count_; uint64_t total_refs_; + std::set<pid_t> pids_; std::string exporter_; std::string name_; std::unordered_map<pid_t, int> fdrefs_; @@ -80,6 +85,7 @@ struct DmaBuffer { auto [it, inserted] = map->insert(std::make_pair(pid, 1)); if (!inserted) it->second++; + pids_.insert(pid); } }; diff --git a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp index 0851fb33c..48901b1da 100644 --- a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp +++ b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp @@ -16,17 +16,19 @@ #include <dirent.h> #include <errno.h> +#include <getopt.h> #include <inttypes.h> +#include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <iostream> #include <fstream> +#include <iostream> +#include <map> +#include <set> #include <sstream> #include <string> #include <vector> -#include <map> -#include <set> #include <android-base/stringprintf.h> #include <dmabufinfo/dmabufinfo.h> @@ -35,15 +37,16 @@ using DmaBuffer = ::android::dmabufinfo::DmaBuffer; [[noreturn]] static void usage(int exit_status) { fprintf(stderr, - "Usage: %s [PID] \n" - "\t If PID is supplied, the dmabuf information for this process is shown.\n" - "\t Otherwise, shows the information for all processes.\n", + "Usage: %s [-ah] [PID] \n" + "-a\t show all dma buffers (ion) in big table, [buffer x process] grid \n" + "-h\t show this help\n" + " \t If PID is supplied, the dmabuf information for that process is shown.\n", getprogname()); exit(exit_status); } -static std::string GetProcessBaseName(pid_t pid) { +static std::string GetProcessComm(const pid_t pid) { std::string pid_path = android::base::StringPrintf("/proc/%d/comm", pid); std::ifstream in{pid_path}; if (!in) return std::string("N/A"); @@ -53,133 +56,211 @@ static std::string GetProcessBaseName(pid_t pid) { return line; } -static void AddPidsToSet(const std::unordered_map<pid_t, int>& map, std::set<pid_t>* set) -{ - for (auto it = map.begin(); it != map.end(); ++it) - set->insert(it->first); -} - -static void PrintDmaBufInfo(const std::vector<DmaBuffer>& bufs) { - std::set<pid_t> pid_set; - std::map<pid_t, int> pid_column; - +static void PrintDmaBufTable(const std::vector<DmaBuffer>& bufs) { if (bufs.empty()) { - std::cout << "dmabuf info not found ¯\\_(ツ)_/¯" << std::endl; + printf("dmabuf info not found ¯\\_(ツ)_/¯\n"); return; } // Find all unique pids in the input vector, create a set - for (int i = 0; i < bufs.size(); i++) { - AddPidsToSet(bufs[i].fdrefs(), &pid_set); - AddPidsToSet(bufs[i].maprefs(), &pid_set); + std::set<pid_t> pid_set; + for (auto& buf : bufs) { + pid_set.insert(buf.pids().begin(), buf.pids().end()); } - int pid_count = 0; + // Format the header string spaced and separated with '|' + printf(" Dmabuf Inode | Size | Ref Counts |"); + for (auto pid : pid_set) { + printf("%16s:%-5d |", GetProcessComm(pid).c_str(), pid); + } + printf("\n"); + + // holds per-process dmabuf size in kB + std::map<pid_t, uint64_t> per_pid_size = {}; + uint64_t dmabuf_total_size = 0; + + // Iterate through all dmabufs and collect per-process sizes, refs + for (auto& buf : bufs) { + printf("%16ju |%13" PRIu64 " kB |%16" PRIu64 " |", static_cast<uintmax_t>(buf.inode()), + buf.size() / 1024, buf.total_refs()); + // Iterate through each process to find out per-process references for each buffer, + // gather total size used by each process etc. + for (pid_t pid : pid_set) { + int pid_refs = 0; + if (buf.fdrefs().count(pid) == 1) { + // Get the total number of ref counts the process is holding + // on this buffer. We don't differentiate between mmap or fd. + pid_refs += buf.fdrefs().at(pid); + if (buf.maprefs().count(pid) == 1) { + pid_refs += buf.maprefs().at(pid); + } + } - std::cout << "\t\t\t\t\t\t"; + if (pid_refs) { + // Add up the per-pid total size. Note that if a buffer is mapped + // in 2 different processes, the size will be shown as mapped or opened + // in both processes. This is intended for visibility. + // + // If one wants to get the total *unique* dma buffers, they can simply + // sum the size of all dma bufs shown by the tool + per_pid_size[pid] += buf.size() / 1024; + printf("%17d refs |", pid_refs); + } else { + printf("%22s |", "--"); + } + } + dmabuf_total_size += buf.size() / 1024; + printf("\n"); + } - // Create a map to convert each unique pid into a column number - for (auto it = pid_set.begin(); it != pid_set.end(); ++it, ++pid_count) { - pid_column.insert(std::make_pair(*it, pid_count)); - std::cout << ::android::base::StringPrintf("[pid: % 4d]\t", *it); + printf("------------------------------------\n"); + printf("%-16s %13" PRIu64 " kB |%16s |", "TOTALS", dmabuf_total_size, "n/a"); + for (auto pid : pid_set) { + printf("%19" PRIu64 " kB |", per_pid_size[pid]); } + printf("\n"); - std::cout << std::endl << "\t\t\t\t\t\t"; + return; +} - for (auto it = pid_set.begin(); it != pid_set.end(); ++it) { - std::cout << ::android::base::StringPrintf("%16s", - GetProcessBaseName(*it).c_str()); +static void PrintDmaBufPerProcess(const std::vector<DmaBuffer>& bufs) { + if (bufs.empty()) { + printf("dmabuf info not found ¯\\_(ツ)_/¯\n"); + return; } - std::cout << std::endl << "\tinode\t\tsize\t\tcount\t"; - for (int i = 0; i < pid_count; i++) { - std::cout << "fd\tmap\t"; + // Create a reverse map from pid to dmabufs + std::unordered_map<pid_t, std::set<ino_t>> pid_to_inodes = {}; + uint64_t total_size = 0; // Total size of dmabufs in the system + uint64_t kernel_rss = 0; // Total size of dmabufs NOT mapped or opened by a process + for (auto& buf : bufs) { + for (auto pid : buf.pids()) { + pid_to_inodes[pid].insert(buf.inode()); + } + total_size += buf.size(); + if (buf.fdrefs().empty() && buf.maprefs().empty()) { + kernel_rss += buf.size(); + } + } + // Create an inode to dmabuf map. We know inodes are unique.. + std::unordered_map<ino_t, DmaBuffer> inode_to_dmabuf; + for (auto buf : bufs) { + inode_to_dmabuf[buf.inode()] = buf; } - std::cout << std::endl; - - auto fds = std::make_unique<int[]>(pid_count); - auto maps = std::make_unique<int[]>(pid_count); - auto pss = std::make_unique<long[]>(pid_count); - memset(pss.get(), 0, sizeof(long) * pid_count); + uint64_t total_rss = 0, total_pss = 0; + for (auto& [pid, inodes] : pid_to_inodes) { + uint64_t pss = 0; + uint64_t rss = 0; + + printf("%16s:%-5d\n", GetProcessComm(pid).c_str(), pid); + printf("%22s %16s %16s %16s %16s\n", "Name", "Rss", "Pss", "nr_procs", "Inode"); + for (auto& inode : inodes) { + DmaBuffer& buf = inode_to_dmabuf[inode]; + printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16zu %16" PRIuMAX "\n", + buf.name().empty() ? "<unknown>" : buf.name().c_str(), buf.size() / 1024, + buf.Pss() / 1024, buf.pids().size(), static_cast<uintmax_t>(buf.inode())); + rss += buf.size(); + pss += buf.Pss(); + } + printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16s\n", "PROCESS TOTAL", rss / 1024, + pss / 1024, ""); + printf("----------------------\n"); + total_rss += rss; + total_pss += pss; + } + printf("dmabuf total: %" PRIu64 " kB kernel_rss: %" PRIu64 " kB userspace_rss: %" PRIu64 + " kB userspace_pss: %" PRIu64 " kB\n ", + total_size / 1024, kernel_rss / 1024, total_rss / 1024, total_pss / 1024); +} - for (auto buf = bufs.begin(); buf != bufs.end(); ++buf) { +static bool ReadDmaBufs(std::vector<DmaBuffer>* bufs) { + bufs->clear(); - std::cout << ::android::base::StringPrintf("%16lu\t%10" PRIu64 "\t%" PRIu64 "\t", - buf->inode(),buf->size(), buf->count()); + if (!ReadDmaBufInfo(bufs)) { + fprintf(stderr, "debugfs entry for dmabuf not available, skipping\n"); + return false; + } - memset(fds.get(), 0, sizeof(int) * pid_count); - memset(maps.get(), 0, sizeof(int) * pid_count); + std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); + if (!dir) { + fprintf(stderr, "Failed to open /proc directory\n"); + bufs->clear(); + return false; + } - for (auto it = buf->fdrefs().begin(); it != buf->fdrefs().end(); ++it) { - fds[pid_column[it->first]] = it->second; - pss[pid_column[it->first]] += buf->size() * it->second / buf->count(); - } + struct dirent* dent; + while ((dent = readdir(dir.get()))) { + if (dent->d_type != DT_DIR) continue; - for (auto it = buf->maprefs().begin(); it != buf->maprefs().end(); ++it) { - maps[pid_column[it->first]] = it->second; - pss[pid_column[it->first]] += buf->size() * it->second / buf->count(); + int pid = atoi(dent->d_name); + if (pid == 0) { + continue; } - for (int i = 0; i < pid_count; i++) { - std::cout << ::android::base::StringPrintf("%d\t%d\t", fds[i], maps[i]); + if (!AppendDmaBufInfo(pid, bufs)) { + fprintf(stderr, "Unable to read dmabuf info for pid %d\n", pid); + bufs->clear(); + return false; } - std::cout << std::endl; - } - std::cout << "-----------------------------------------" << std::endl; - std::cout << "PSS "; - for (int i = 0; i < pid_count; i++) { - std::cout << ::android::base::StringPrintf("%15ldK", pss[i] / 1024); } - std::cout << std::endl; + + return true; } int main(int argc, char* argv[]) { - pid_t pid = -1; - std::vector<DmaBuffer> bufs; - bool show_all = true; - - if (argc > 1) { - if (sscanf(argv[1], "%d", &pid) == 1) { - show_all = false; - } - else { - usage(EXIT_FAILURE); + struct option longopts[] = {{"all", no_argument, nullptr, 'a'}, + {"help", no_argument, nullptr, 'h'}, + {0, 0, nullptr, 0}}; + + int opt; + bool show_table = false; + while ((opt = getopt_long(argc, argv, "ah", longopts, nullptr)) != -1) { + switch (opt) { + case 'a': + show_table = true; + break; + case 'h': + usage(EXIT_SUCCESS); + default: + usage(EXIT_FAILURE); } } - if (show_all) { - if (!ReadDmaBufInfo(&bufs)) { - std::cerr << "debugfs entry for dmabuf not available, skipping" << std::endl; - bufs.clear(); + pid_t pid = -1; + if (optind < argc) { + if (show_table) { + fprintf(stderr, "Invalid arguments: -a does not need arguments\n"); + usage(EXIT_FAILURE); } - std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); - if (!dir) { - std::cerr << "Failed to open /proc directory" << std::endl; - exit(EXIT_FAILURE); + if (optind != (argc - 1)) { + fprintf(stderr, "Invalid arguments - only one [PID] argument is allowed\n"); + usage(EXIT_FAILURE); } - struct dirent* dent; - while ((dent = readdir(dir.get()))) { - if (dent->d_type != DT_DIR) continue; - - int matched = sscanf(dent->d_name, "%d", &pid); - if (matched != 1) { - continue; - } - - if (!AppendDmaBufInfo(pid, &bufs)) { - std::cerr << "Unable to read dmabuf info for pid " << pid << std::endl; - exit(EXIT_FAILURE); - } + pid = atoi(argv[optind]); + if (pid == 0) { + fprintf(stderr, "Invalid process id %s\n", argv[optind]); + usage(EXIT_FAILURE); } - } else { + } + + std::vector<DmaBuffer> bufs; + if (pid != -1) { if (!ReadDmaBufInfo(pid, &bufs)) { - std::cerr << "Unable to read dmabuf info" << std::endl; + fprintf(stderr, "Unable to read dmabuf info for %d\n", pid); exit(EXIT_FAILURE); } + } else { + if (!ReadDmaBufs(&bufs)) exit(EXIT_FAILURE); } - PrintDmaBufInfo(bufs); - return 0; -} + // Show the old dmabuf table, inode x process + if (show_table) { + PrintDmaBufTable(bufs); + return 0; + } + PrintDmaBufPerProcess(bufs); + + return 0; +} diff --git a/libmeminfo/pageacct.cpp b/libmeminfo/pageacct.cpp index 0a26c0818..cb17af8ab 100644 --- a/libmeminfo/pageacct.cpp +++ b/libmeminfo/pageacct.cpp @@ -81,7 +81,8 @@ bool PageAcct::PageFlags(uint64_t pfn, uint64_t* flags) { if (!InitPageAcct()) return false; } - if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) < 0) { + if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) != + sizeof(uint64_t)) { PLOG(ERROR) << "Failed to read page flags for page " << pfn; return false; } @@ -95,7 +96,8 @@ bool PageAcct::PageMapCount(uint64_t pfn, uint64_t* mapcount) { if (!InitPageAcct()) return false; } - if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) < 0) { + if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) != + sizeof(uint64_t)) { PLOG(ERROR) << "Failed to read map count for page " << pfn; return false; } @@ -130,7 +132,7 @@ int PageAcct::GetPageIdle(uint64_t pfn) const { off64_t offset = pfn_to_idle_bitmap_offset(pfn); uint64_t idle_bits; - if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) < 0) { + if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) != sizeof(uint64_t)) { PLOG(ERROR) << "Failed to read page idle bitmap for page " << pfn; return -errno; } diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp index 934d65c9d..a8b43c189 100644 --- a/libmeminfo/procmeminfo.cpp +++ b/libmeminfo/procmeminfo.cpp @@ -27,6 +27,7 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include <android-base/file.h> #include <android-base/logging.h> @@ -278,68 +279,89 @@ bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle) { bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle) { PageAcct& pinfo = PageAcct::Instance(); - uint64_t pagesz = getpagesize(); - uint64_t num_pages = (vma.end - vma.start) / pagesz; - - std::unique_ptr<uint64_t[]> pg_frames(new uint64_t[num_pages]); - uint64_t first = vma.start / pagesz; - if (pread64(pagemap_fd, pg_frames.get(), num_pages * sizeof(uint64_t), - first * sizeof(uint64_t)) < 0) { - PLOG(ERROR) << "Failed to read page frames from page map for pid: " << pid_; + if (get_wss && use_pageidle && !pinfo.InitPageAcct(true)) { + LOG(ERROR) << "Failed to init idle page accounting"; return false; } - if (get_wss && use_pageidle) { - if (!pinfo.InitPageAcct(true)) { - LOG(ERROR) << "Failed to init idle page accounting"; - return false; - } - } - - std::unique_ptr<uint64_t[]> pg_flags(new uint64_t[num_pages]); - std::unique_ptr<uint64_t[]> pg_counts(new uint64_t[num_pages]); - for (uint64_t i = 0; i < num_pages; ++i) { + uint64_t pagesz = getpagesize(); + size_t num_pages = (vma.end - vma.start) / pagesz; + size_t first_page = vma.start / pagesz; + + std::vector<uint64_t> page_cache; + size_t cur_page_cache_index = 0; + size_t num_in_page_cache = 0; + size_t num_leftover_pages = num_pages; + for (size_t cur_page = first_page; cur_page < first_page + num_pages; ++cur_page) { if (!get_wss) { vma.usage.vss += pagesz; } - uint64_t p = pg_frames[i]; - if (!PAGE_PRESENT(p) && !PAGE_SWAPPED(p)) continue; - if (PAGE_SWAPPED(p)) { + // Cache page map data. + if (cur_page_cache_index == num_in_page_cache) { + static constexpr size_t kMaxPages = 2048; + num_leftover_pages -= num_in_page_cache; + if (num_leftover_pages > kMaxPages) { + num_in_page_cache = kMaxPages; + } else { + num_in_page_cache = num_leftover_pages; + } + page_cache.resize(num_in_page_cache); + size_t total_bytes = page_cache.size() * sizeof(uint64_t); + ssize_t bytes = pread64(pagemap_fd, page_cache.data(), total_bytes, + cur_page * sizeof(uint64_t)); + if (bytes != total_bytes) { + if (bytes == -1) { + PLOG(ERROR) << "Failed to read page data at offset 0x" << std::hex + << cur_page * sizeof(uint64_t); + } else { + LOG(ERROR) << "Failed to read page data at offset 0x" << std::hex + << cur_page * sizeof(uint64_t) << std::dec << " read bytes " << bytes + << " expected bytes " << total_bytes; + } + return false; + } + cur_page_cache_index = 0; + } + + uint64_t page_info = page_cache[cur_page_cache_index++]; + if (!PAGE_PRESENT(page_info) && !PAGE_SWAPPED(page_info)) continue; + + if (PAGE_SWAPPED(page_info)) { vma.usage.swap += pagesz; - swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(p)); + swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(page_info)); continue; } - uint64_t page_frame = PAGE_PFN(p); - if (!pinfo.PageFlags(page_frame, &pg_flags[i])) { + uint64_t page_frame = PAGE_PFN(page_info); + uint64_t cur_page_flags; + if (!pinfo.PageFlags(page_frame, &cur_page_flags)) { LOG(ERROR) << "Failed to get page flags for " << page_frame << " in process " << pid_; swap_offsets_.clear(); return false; } // skip unwanted pages from the count - if ((pg_flags[i] & pgflags_mask_) != pgflags_) continue; + if ((cur_page_flags & pgflags_mask_) != pgflags_) continue; - if (!pinfo.PageMapCount(page_frame, &pg_counts[i])) { + uint64_t cur_page_counts; + if (!pinfo.PageMapCount(page_frame, &cur_page_counts)) { LOG(ERROR) << "Failed to get page count for " << page_frame << " in process " << pid_; swap_offsets_.clear(); return false; } // Page was unmapped between the presence check at the beginning of the loop and here. - if (pg_counts[i] == 0) { - pg_frames[i] = 0; - pg_flags[i] = 0; + if (cur_page_counts == 0) { continue; } - bool is_dirty = !!(pg_flags[i] & (1 << KPF_DIRTY)); - bool is_private = (pg_counts[i] == 1); + bool is_dirty = !!(cur_page_flags & (1 << KPF_DIRTY)); + bool is_private = (cur_page_counts == 1); // Working set if (get_wss) { bool is_referenced = use_pageidle ? (pinfo.IsPageIdle(page_frame) == 1) - : !!(pg_flags[i] & (1 << KPF_REFERENCED)); + : !!(cur_page_flags & (1 << KPF_REFERENCED)); if (!is_referenced) { continue; } @@ -351,7 +373,7 @@ bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_ vma.usage.rss += pagesz; vma.usage.uss += is_private ? pagesz : 0; - vma.usage.pss += pagesz / pg_counts[i]; + vma.usage.pss += pagesz / cur_page_counts; if (is_private) { vma.usage.private_dirty += is_dirty ? pagesz : 0; vma.usage.private_clean += is_dirty ? 0 : pagesz; diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp index cb3757dba..1e44ff9bd 100644 --- a/libmeminfo/tools/procrank.cpp +++ b/libmeminfo/tools/procrank.cpp @@ -348,7 +348,7 @@ int main(int argc, char* argv[]) { auto rss_sort = [](ProcessRecord& a, ProcessRecord& b) { MemUsage stats_a = show_wss ? a.Wss() : a.Usage(); MemUsage stats_b = show_wss ? b.Wss() : b.Usage(); - return reverse_sort ? stats_a.rss < stats_b.pss : stats_a.pss > stats_b.pss; + return reverse_sort ? stats_a.rss < stats_b.rss : stats_a.rss > stats_b.rss; }; auto vss_sort = [](ProcessRecord& a, ProcessRecord& b) { diff --git a/libmeminfo/vts/AndroidTest.xml b/libmeminfo/vts/AndroidTest.xml index 530d16ef0..9614025ae 100644 --- a/libmeminfo/vts/AndroidTest.xml +++ b/libmeminfo/vts/AndroidTest.xml @@ -24,6 +24,7 @@ <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_meminfo_test/vts_meminfo_test" /> <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_meminfo_test/vts_meminfo_test" /> <option name="binary-test-type" value="gtest"/> + <option name="precondition-first-api-level" value="29" /> <option name="test-timeout" value="10m"/> </test> </configuration> diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c index 3700c31fe..c7dfce68e 100644 --- a/lmkd/lmkd.c +++ b/lmkd/lmkd.c @@ -83,6 +83,7 @@ #define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes" #define ZONEINFO_PATH "/proc/zoneinfo" #define MEMINFO_PATH "/proc/meminfo" +#define PROC_STATUS_TGID_FIELD "Tgid:" #define TRACE_MARKER_PATH "/sys/kernel/debug/tracing/trace_marker" #define LINE_MAX 128 #define MAX_NR_ZONES 6 @@ -588,6 +589,49 @@ static inline long get_time_diff_ms(struct timespec *from, (to->tv_nsec - from->tv_nsec) / (long)NS_PER_MS; } +static int proc_get_tgid(int pid) { + char path[PATH_MAX]; + char buf[PAGE_SIZE]; + int fd; + ssize_t size; + char *pos; + int64_t tgid = -1; + + snprintf(path, PATH_MAX, "/proc/%d/status", pid); + fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return -1; + } + + size = read_all(fd, buf, sizeof(buf) - 1); + if (size < 0) { + goto out; + } + buf[size] = 0; + + pos = buf; + while (true) { + pos = strstr(pos, PROC_STATUS_TGID_FIELD); + /* Stop if TGID tag not found or found at the line beginning */ + if (pos == NULL || pos == buf || pos[-1] == '\n') { + break; + } + pos++; + } + + if (pos == NULL) { + goto out; + } + + pos += strlen(PROC_STATUS_TGID_FIELD); + while (*pos == ' ') pos++; + parse_int64(pos, &tgid); + +out: + close(fd); + return (int)tgid; +} + static void cmd_procprio(LMKD_CTRL_PACKET packet) { struct proc *procp; char path[80]; @@ -596,6 +640,7 @@ static void cmd_procprio(LMKD_CTRL_PACKET packet) { struct lmk_procprio params; bool is_system_server; struct passwd *pwdrec; + int tgid; lmkd_pack_get_procprio(packet, ¶ms); @@ -605,6 +650,14 @@ static void cmd_procprio(LMKD_CTRL_PACKET packet) { return; } + /* Check if registered process is a thread group leader */ + tgid = proc_get_tgid(params.pid); + if (tgid >= 0 && tgid != params.pid) { + ALOGE("Attempt to register a task that is not a thread group leader (tid %d, tgid %d)", + params.pid, tgid); + return; + } + /* gid containing AID_READPROC required */ /* CAP_SYS_RESOURCE required */ /* CAP_DAC_OVERRIDE required */ @@ -1754,6 +1807,7 @@ static int last_killed_pid = -1; static int kill_one_process(struct proc* procp, int min_oom_score) { int pid = procp->pid; uid_t uid = procp->uid; + int tgid; char *taskname; long tasksize; int r; @@ -1767,6 +1821,12 @@ static int kill_one_process(struct proc* procp, int min_oom_score) { (void)(min_oom_score); #endif + tgid = proc_get_tgid(pid); + if (tgid >= 0 && tgid != pid) { + ALOGE("Possible pid reuse detected (pid %d, tgid %d)!", pid, tgid); + goto out; + } + taskname = proc_get_name(pid); if (!taskname) { goto out; diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt index 84b308d0e..c95f60fb0 100644 --- a/rootdir/etc/ld.config.txt +++ b/rootdir/etc/ld.config.txt @@ -143,6 +143,7 @@ namespace.default.link.runtime.shared_libs += libandroidicu.so # TODO(b/122876336): Remove libpac.so once it's migrated to Webview namespace.default.link.runtime.shared_libs += libpac.so +namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% # When libnetd_resolv.so can't be found in the default namespace, search for it # in the resolv namespace. Don't allow any other libraries from the resolv namespace @@ -363,7 +364,7 @@ namespace.vndk.asan.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER # The "vndk" namespace links to "default" namespace for LLNDK libs and links to # "sphal" namespace for vendor libs. The ordering matters. The "default" # namespace has higher priority than the "sphal" namespace. -namespace.vndk.links = default,sphal +namespace.vndk.links = default,sphal,runtime # When these NDK libs are required inside this namespace, then it is redirected # to the default namespace. This is possible since their ABI is stable across @@ -371,6 +372,8 @@ namespace.vndk.links = default,sphal namespace.vndk.link.default.shared_libs = %LLNDK_LIBRARIES% namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% +namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% + # Allow VNDK-SP extensions to use vendor libraries namespace.vndk.link.sphal.allow_all_shared_libs = true @@ -423,8 +426,10 @@ namespace.default.asan.permitted.paths += /odm namespace.default.asan.permitted.paths += /data/asan/vendor namespace.default.asan.permitted.paths += /vendor -namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS% -namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES% +namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS%,runtime +namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% +namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES% +namespace.default.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.default.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES% namespace.default.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES% namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES% @@ -477,13 +482,15 @@ namespace.vndk.asan.search.paths += /system/${LIB}/vndk%VNDK_VER% # Android releases. The links here should be identical to that of the # 'vndk_in_system' namespace, except for the link between 'vndk' and # 'vndk_in_system'. -namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS% +namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS%,runtime namespace.vndk.link.system.shared_libs = %LLNDK_LIBRARIES% namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.vndk.link.default.allow_all_shared_libs = true +namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% + namespace.vndk.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES% ############################################################################### @@ -515,6 +522,7 @@ namespace.system.link.runtime.shared_libs += libnativehelper.so namespace.system.link.runtime.shared_libs += libnativeloader.so # Workaround for b/124772622 namespace.system.link.runtime.shared_libs += libandroidicu.so +namespace.system.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% ############################################################################### # "vndk_in_system" namespace @@ -553,7 +561,8 @@ namespace.vndk_in_system.whitelisted = %VNDK_USING_CORE_VARIANT_LIBRARIES% # 1. 'vndk_in_system' needs to be freely linked back to 'vndk'. # 2. 'vndk_in_system' does not need to link to 'default', as any library that # requires anything vendor would not be a vndk_in_system library. -namespace.vndk_in_system.links = vndk,system +namespace.vndk_in_system.links = vndk,system,runtime +namespace.vndk_in_system.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% namespace.vndk_in_system.link.system.shared_libs = %LLNDK_LIBRARIES% namespace.vndk_in_system.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% @@ -596,6 +605,7 @@ namespace.default.link.runtime.shared_libs += libandroidicu.so # TODO(b/122876336): Remove libpac.so once it's migrated to Webview namespace.default.link.runtime.shared_libs += libpac.so +namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.default.link.resolv.shared_libs = libnetd_resolv.so @@ -684,3 +694,5 @@ namespace.default.isolated = false namespace.default.search.paths = /system/${LIB} namespace.default.search.paths += /%PRODUCT%/${LIB} namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB} + +namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt index 5db7698f4..564255926 100644 --- a/rootdir/etc/ld.config.vndk_lite.txt +++ b/rootdir/etc/ld.config.vndk_lite.txt @@ -417,6 +417,7 @@ namespace.default.link.runtime.shared_libs += libandroidicu.so # TODO(b/122876336): Remove libpac.so once it's migrated to Webview namespace.default.link.runtime.shared_libs += libpac.so +namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.default.link.resolv.shared_libs = libnetd_resolv.so diff --git a/rootdir/init.rc b/rootdir/init.rc index 171e02a3d..ed957e419 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -688,6 +688,7 @@ on boot # to make it too large, since it may bring userdata loss, if they # are not aware of using fsync()/sync() to prepare sudden power-cut. write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200 + write /sys/fs/f2fs/${dev.mnt.blk.data}/gc_urgent_sleep_time 50 # Permissions for System Server and daemons. chown radio system /sys/android_power/state @@ -809,6 +810,9 @@ on property:vold.decrypt=trigger_shutdown_framework on property:sys.boot_completed=1 bootchart stop + # Setup per_boot directory so other .rc could start to use it on boot_completed + exec - system system -- /bin/rm -rf /data/per_boot + mkdir /data/per_boot 0700 system system # system server cannot write to /proc/sys files, # and chown/chmod does not work for /proc/sys/ entries. diff --git a/rootdir/update_and_install_ld_config.mk b/rootdir/update_and_install_ld_config.mk index f62c3df5b..12828683f 100644 --- a/rootdir/update_and_install_ld_config.mk +++ b/rootdir/update_and_install_ld_config.mk @@ -88,7 +88,7 @@ endif # ifneq ($(lib_list_from_prebuilts),true) # $(2): output file with the filtered list of lib names $(LOCAL_BUILT_MODULE): private-filter-out-private-libs = \ paste -sd ":" $(1) > $(2) && \ - cat $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) | xargs -n 1 -I privatelib bash -c "sed -i.bak 's/privatelib//' $(2)" && \ + while read -r privatelib; do sed -i.bak "s/$$privatelib//" $(2) ; done < $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) && \ sed -i.bak -e 's/::\+/:/g ; s/^:\+// ; s/:\+$$//' $(2) && \ rm -f $(2).bak $(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES_FILE := $(llndk_libraries_file) @@ -139,8 +139,9 @@ else endif $(hide) echo -n > $(PRIVATE_INTERMEDIATES_DIR)/private_llndk && \ - cat $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) | \ - xargs -n 1 -I privatelib bash -c "(grep privatelib $(PRIVATE_LLNDK_LIBRARIES_FILE) || true) >> $(PRIVATE_INTERMEDIATES_DIR)/private_llndk" && \ + while read -r privatelib; \ + do (grep $$privatelib $(PRIVATE_LLNDK_LIBRARIES_FILE) || true) >> $(PRIVATE_INTERMEDIATES_DIR)/private_llndk ; \ + done < $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) && \ paste -sd ":" $(PRIVATE_INTERMEDIATES_DIR)/private_llndk | \ sed -i.bak -e "s?%PRIVATE_LLNDK_LIBRARIES%?$$(cat -)?g" $@ diff --git a/usbd/usbd.cpp b/usbd/usbd.cpp index 191fb92fb..6e24d8e78 100644 --- a/usbd/usbd.cpp +++ b/usbd/usbd.cpp @@ -24,8 +24,6 @@ #include <hidl/HidlTransportSupport.h> -#define PERSISTENT_USB_CONFIG "persist.sys.usb.config" - using android::base::GetProperty; using android::base::SetProperty; using android::hardware::configureRpcThreadpool; @@ -34,14 +32,15 @@ using android::hardware::usb::gadget::V1_0::IUsbGadget; using android::hardware::Return; int main(int /*argc*/, char** /*argv*/) { - configureRpcThreadpool(1, true /*callerWillJoin*/); + if (GetProperty("ro.bootmode", "") == "charger") exit(0); + configureRpcThreadpool(1, true /*callerWillJoin*/); android::sp<IUsbGadget> gadget = IUsbGadget::getService(); Return<void> ret; if (gadget != nullptr) { LOG(INFO) << "Usb HAL found."; - std::string function = GetProperty(PERSISTENT_USB_CONFIG, ""); + std::string function = GetProperty("persist.sys.usb.config", ""); if (function == "adb") { LOG(INFO) << "peristent prop is adb"; SetProperty("ctl.start", "adbd"); |