Merge "meminfo: Pull ReadVmallocInfo() out of the SysMemInfo class."
diff --git a/adb/client/line_printer.cpp b/adb/client/line_printer.cpp
index 4dc2d28..50c03e8 100644
--- a/adb/client/line_printer.cpp
+++ b/adb/client/line_printer.cpp
@@ -31,6 +31,8 @@
// Stuff from ninja's util.h that's needed below.
#include <vector>
using namespace std;
+// This does not account for multiple UTF-8 bytes corresponding to a single Unicode code point, or
+// multiple code points corresponding to a single grapheme cluster (user-perceived character).
string ElideMiddle(const string& str, size_t width) {
const int kMargin = 3; // Space for "...".
string result = str;
@@ -85,9 +87,10 @@
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(console_, &csbi);
- // TODO: std::wstring to_print_wide; if (!android::base::UTF8ToWide(to_print, &to_print_wide)...
- // TODO: wstring ElideMiddle.
to_print = ElideMiddle(to_print, static_cast<size_t>(csbi.dwSize.X));
+ std::wstring to_print_wide;
+ // ElideMiddle may create invalid UTF-8, so ignore conversion errors.
+ (void)android::base::UTF8ToWide(to_print, &to_print_wide);
// We don't want to have the cursor spamming back and forth, so instead of
// printf use WriteConsoleOutput which updates the contents of the buffer,
// but doesn't move the cursor position.
@@ -100,12 +103,10 @@
};
vector<CHAR_INFO> char_data(csbi.dwSize.X);
for (size_t i = 0; i < static_cast<size_t>(csbi.dwSize.X); ++i) {
- // TODO: UnicodeChar instead of AsciiChar, to_print_wide[i].
- char_data[i].Char.AsciiChar = i < to_print.size() ? to_print[i] : ' ';
- char_data[i].Attributes = csbi.wAttributes;
+ char_data[i].Char.UnicodeChar = i < to_print_wide.size() ? to_print_wide[i] : L' ';
+ char_data[i].Attributes = csbi.wAttributes;
}
- // TODO: WriteConsoleOutputW.
- WriteConsoleOutput(console_, &char_data[0], buf_size, zero_zero, &target);
+ WriteConsoleOutputW(console_, &char_data[0], buf_size, zero_zero, &target);
#else
// Limit output to width of the terminal if provided so we don't cause
// line-wrapping.
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index dbc8920..d587589 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -719,7 +719,7 @@
/**************************************************************************/
/**************************************************************************/
-static int _init_winsock(void) {
+static void _init_winsock() {
static std::once_flag once;
std::call_once(once, []() {
WSADATA wsaData;
@@ -743,11 +743,8 @@
// crypt32.dll which calls atexit() which tries to acquire the C
// Runtime lock that the other thread holds.
});
- return 0;
}
-static int _winsock_init = _init_winsock();
-
// Map a socket type to an explicit socket protocol instead of using the socket
// protocol of 0. Explicit socket protocols are used by most apps and we should
// do the same to reduce the chance of exercising uncommon code-paths that might
@@ -2621,14 +2618,13 @@
}
// Shadow UTF-8 environment variable name/value pairs that are created from
-// _wenviron the first time that adb_getenv() is called. Note that this is not
-// currently updated if putenv, setenv, unsetenv are called. Note that no
-// thread synchronization is done, but we're called early enough in
+// _wenviron by _init_env(). Note that this is not currently updated if putenv, setenv, unsetenv are
+// called. Note that no thread synchronization is done, but we're called early enough in
// single-threaded startup that things work ok.
static auto& g_environ_utf8 = *new std::unordered_map<std::string, char*>();
-// Make sure that shadow UTF-8 environment variables are setup.
-static void _ensure_env_setup() {
+// Setup shadow UTF-8 environment variables.
+static void _init_env() {
// If some name/value pairs exist, then we've already done the setup below.
if (g_environ_utf8.size() != 0) {
return;
@@ -2681,8 +2677,6 @@
// Version of getenv() that takes a UTF-8 environment variable name and
// retrieves a UTF-8 value. Case-insensitive to match getenv() on Windows.
char* adb_getenv(const char* name) {
- _ensure_env_setup();
-
// Case-insensitive search by searching for lowercase name in a map of
// lowercase names.
const auto it = g_environ_utf8.find(ToLower(std::string(name)));
@@ -2757,3 +2751,65 @@
return 0;
}
+
+#if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
+#if !defined(DISABLE_NEWLINE_AUTO_RETURN)
+#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
+#endif
+
+static void _init_console() {
+ DWORD old_out_console_mode;
+
+ const HANDLE out = _get_console_handle(STDOUT_FILENO, &old_out_console_mode);
+ if (out == nullptr) {
+ return;
+ }
+
+ // Try to use ENABLE_VIRTUAL_TERMINAL_PROCESSING on the output console to process virtual
+ // terminal sequences on newer versions of Windows 10 and later.
+ // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ // On older OSes that don't support the flag, SetConsoleMode() will return an error.
+ // ENABLE_VIRTUAL_TERMINAL_PROCESSING also solves a problem where the last column of the
+ // console cannot be overwritten.
+ //
+ // Note that we don't use DISABLE_NEWLINE_AUTO_RETURN because it doesn't seem to be necessary.
+ // If we use DISABLE_NEWLINE_AUTO_RETURN, _console_write_utf8() would need to be modified to
+ // translate \n to \r\n.
+ if (!SetConsoleMode(out, old_out_console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
+ return;
+ }
+
+ // If SetConsoleMode() succeeded, the console supports virtual terminal processing, so we
+ // should set the TERM env var to match so that it will be propagated to adbd on devices.
+ //
+ // Below's direct manipulation of env vars and not g_environ_utf8 assumes that _init_env() has
+ // not yet been called. If this fails, _init_env() should be called after _init_console().
+ if (g_environ_utf8.size() > 0) {
+ LOG(FATAL) << "environment variables have already been converted to UTF-8";
+ }
+
+#pragma push_macro("getenv")
+#undef getenv
+#pragma push_macro("putenv")
+#undef putenv
+ if (getenv("TERM") == nullptr) {
+ // This is the same TERM value used by Gnome Terminal and the version of ssh included with
+ // Windows.
+ putenv("TERM=xterm-256color");
+ }
+#pragma pop_macro("putenv")
+#pragma pop_macro("getenv")
+}
+
+static bool _init_sysdeps() {
+ // _init_console() depends on _init_env() not being called yet.
+ _init_console();
+ _init_env();
+ _init_winsock();
+ return true;
+}
+
+static bool _sysdeps_init = _init_sysdeps();
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 0f89467..3908683 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -137,9 +137,9 @@
bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
// readonly filesystem, can not be mount -o remount,rw
- // if squashfs or if free space is (near) zero making such a remount
+ // for squashfs, erofs or if free space is (near) zero making such a remount
// virtually useless, or if there are shared blocks that prevent remount,rw
- if ("squashfs" == entry->fs_type || !fs_mgr_filesystem_has_space(entry->mount_point)) {
+ if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
return true;
}
if (entry->fs_mgr_flags.logical) {
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
index 71b39a9..164fc91 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -220,7 +220,7 @@
}
static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
- uint64_t file_size) {
+ uint64_t file_size, std::function<bool(uint64_t, uint64_t)> on_progress) {
// Reserve space for the file on the file system and write it out to make sure the extents
// don't come back unwritten. Return from this function with the kernel file offset set to 0.
// If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
@@ -245,12 +245,22 @@
return false;
}
+ int permille = -1;
for (; offset < file_size; offset += blocksz) {
if (!::android::base::WriteFully(file_fd, buffer.get(), blocksz)) {
PLOG(ERROR) << "Failed to write" << blocksz << " bytes at offset" << offset
<< " in file " << file_path;
return false;
}
+ // Don't invoke the callback every iteration - wait until a significant
+ // chunk (here, 1/1000th) of the data has been processed.
+ int new_permille = (static_cast<uint64_t>(offset) * 1000) / file_size;
+ if (new_permille != permille) {
+ if (on_progress && !on_progress(offset, file_size)) {
+ return false;
+ }
+ permille = new_permille;
+ }
}
if (lseek64(file_fd, 0, SEEK_SET) < 0) {
@@ -264,6 +274,10 @@
return false;
}
+ // Send one last progress notification.
+ if (on_progress && !on_progress(file_size, file_size)) {
+ return false;
+ }
return true;
}
@@ -412,7 +426,8 @@
return last_extent_seen;
}
-FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create) {
+FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create,
+ std::function<bool(uint64_t, uint64_t)> progress) {
// if 'create' is false, open an existing file and do not truncate.
int open_flags = O_RDWR | O_CLOEXEC;
if (create) {
@@ -474,7 +489,7 @@
}
if (create) {
- if (!AllocateFile(file_fd, abs_path, blocksz, file_size)) {
+ if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) {
LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size
<< " bytes";
cleanup(abs_path, create);
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
index 6dff0e8..5101537 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
@@ -83,6 +83,25 @@
EXPECT_EQ(access(testfile.c_str(), F_OK), 0);
}
+TEST_F(FiemapWriterTest, CheckProgress) {
+ std::vector<uint64_t> expected{
+ 0,
+ 4096,
+ };
+ size_t invocations = 0;
+ auto callback = [&](uint64_t done, uint64_t total) -> bool {
+ EXPECT_LT(invocations, expected.size());
+ EXPECT_EQ(done, expected[invocations]);
+ EXPECT_EQ(total, 4096);
+ invocations++;
+ return true;
+ };
+
+ auto ptr = FiemapWriter::Open(testfile, 4096, true, std::move(callback));
+ EXPECT_NE(ptr, nullptr);
+ EXPECT_EQ(invocations, 2);
+}
+
TEST_F(FiemapWriterTest, CheckBlockDevicePath) {
FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096);
EXPECT_EQ(fptr->size(), 4096);
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
index ae61344..ab78f93 100644
--- a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
+++ b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <functional>
#include <string>
#include <vector>
@@ -36,9 +37,13 @@
public:
// Factory method for FiemapWriter.
// The method returns FiemapUniquePtr that contains all the data necessary to be able to write
- // to the given file directly using raw block i/o.
+ // to the given file directly using raw block i/o. The optional progress callback will be
+ // invoked, if create is true, while the file is being initialized. It receives the bytes
+ // written and the number of total bytes. If the callback returns false, the operation will
+ // fail.
static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size,
- bool create = true);
+ bool create = true,
+ std::function<bool(uint64_t, uint64_t)> progress = {});
// Syncs block device writes.
bool Flush() const;
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 80bf84a..2127b96 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -109,6 +109,7 @@
libbase \
libutils \
libcutils \
+ libprocessgroup \
liblog \
libm \
libc \
diff --git a/init/selinux.cpp b/init/selinux.cpp
index c0fc3ce..d93e9ec 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -304,13 +304,18 @@
if (!GetVendorMappingVersion(&vend_plat_vers)) {
return false;
}
- std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+ std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");
if (access(product_policy_cil_file.c_str(), F_OK) == -1) {
product_policy_cil_file.clear();
}
+ std::string product_mapping_file("/product/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+ if (access(product_mapping_file.c_str(), F_OK) == -1) {
+ product_mapping_file.clear();
+ }
+
// vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace
// nonplat_sepolicy.cil.
std::string plat_pub_versioned_cil_file("/vendor/etc/selinux/plat_pub_versioned.cil");
@@ -340,7 +345,7 @@
"-m", "-M", "true", "-G", "-N",
// Target the highest policy language version supported by the kernel
"-c", version_as_string.c_str(),
- mapping_file.c_str(),
+ plat_mapping_file.c_str(),
"-o", compiled_sepolicy,
// We don't care about file_contexts output by the compiler
"-f", "/sys/fs/selinux/null", // /dev/null is not yet available
@@ -350,6 +355,9 @@
if (!product_policy_cil_file.empty()) {
compile_args.push_back(product_policy_cil_file.c_str());
}
+ if (!product_mapping_file.empty()) {
+ compile_args.push_back(product_mapping_file.c_str());
+ }
if (!plat_pub_versioned_cil_file.empty()) {
compile_args.push_back(plat_pub_versioned_cil_file.c_str());
}
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 4291212..0dbbc3f 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -66,7 +66,6 @@
"load_file.cpp",
"native_handle.cpp",
"record_stream.cpp",
- "sched_policy.cpp",
"sockets.cpp",
"strdup16to8.cpp",
"strdup8to16.cpp",
@@ -178,8 +177,12 @@
"libbase_headers",
"libcutils_headers",
"libutils_headers",
+ "libprocessgroup_headers",
],
- export_header_lib_headers: ["libcutils_headers"],
+ export_header_lib_headers: [
+ "libcutils_headers",
+ "libprocessgroup_headers",
+ ],
local_include_dirs: ["include"],
cflags: [
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index cf91b76..538ff6b 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -17,67 +17,10 @@
#ifndef __CUTILS_SCHED_POLICY_H
#define __CUTILS_SCHED_POLICY_H
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/*
- * Check if Linux kernel enables CPUSETS feature.
- *
- * Return value: 1 if Linux kernel CONFIG_CPUSETS=y; 0 otherwise.
+ * For backwards compatibility only
+ * New users should include processgroup/sched_policy.h directly
*/
-extern bool cpusets_enabled();
-
-/*
- * Check if Linux kernel enables SCHEDTUNE feature (only available in Android
- * common kernel or Linaro LSK, not in mainline Linux as of v4.9)
- *
- * Return value: 1 if Linux kernel CONFIG_CGROUP_SCHEDTUNE=y; 0 otherwise.
- */
-extern bool schedboost_enabled();
-
-/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
-typedef enum {
- SP_DEFAULT = -1,
- SP_BACKGROUND = 0,
- SP_FOREGROUND = 1,
- SP_SYSTEM = 2, // can't be used with set_sched_policy()
- SP_AUDIO_APP = 3,
- SP_AUDIO_SYS = 4,
- SP_TOP_APP = 5,
- SP_RT_APP = 6,
- SP_RESTRICTED = 7,
- SP_CNT,
- SP_MAX = SP_CNT - 1,
- SP_SYSTEM_DEFAULT = SP_FOREGROUND,
-} SchedPolicy;
-
-extern int set_cpuset_policy(int tid, SchedPolicy policy);
-
-/* Assign thread tid to the cgroup associated with the specified policy.
- * If the thread is a thread group leader, that is it's gettid() == getpid(),
- * then the other threads in the same thread group are _not_ affected.
- * On platforms which support gettid(), zero tid means current thread.
- * Return value: 0 for success, or -errno for error.
- */
-extern int set_sched_policy(int tid, SchedPolicy policy);
-
-/* Return the policy associated with the cgroup of thread tid via policy pointer.
- * On platforms which support gettid(), zero tid means current thread.
- * Return value: 0 for success, or -1 for error and set errno.
- */
-extern int get_sched_policy(int tid, SchedPolicy *policy);
-
-/* Return a displayable string corresponding to policy.
- * Return value: non-NULL NUL-terminated name of unspecified length;
- * the caller is responsible for displaying the useful part of the string.
- */
-extern const char *get_sched_policy_name(SchedPolicy policy);
-
-#ifdef __cplusplus
-}
-#endif
+#include <processgroup/sched_policy.h>
#endif /* __CUTILS_SCHED_POLICY_H */
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 7884190..72ae559 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -59,6 +59,7 @@
"libcutils",
"liblog",
"libbase",
+ "libprocessgroup",
]
cc_test {
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 4fd36f5..bd7a551 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -73,6 +73,7 @@
cflags: ["-DFAKE_LOG_DEVICE=1"],
},
android: {
+ version_script: "liblog.map.txt",
srcs: liblog_target_sources,
// AddressSanitizer runtime library depends on liblog.
sanitize: {
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 015c9cb..191ef1b 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -59,3 +59,24 @@
android_log_reset; #vndk
android_log_parser_reset; #vndk
};
+
+LIBLOG_PRIVATE {
+ global:
+ __android_log_bswrite;
+ __android_log_btwrite;
+ __android_log_bwrite;
+ __android_log_close;
+ __android_log_pmsg_file_read;
+ __android_log_pmsg_file_write;
+ __android_log_security;
+ __android_log_security_bswrite;
+ __android_logger_get_buffer_size;
+ __android_logger_property_get_bool;
+ android_openEventTagMap;
+ android_log_processBinaryLogBuffer;
+ android_log_processLogBuffer;
+ android_log_read_next;
+ android_log_write_list_buffer;
+ android_lookupEventTagNum;
+ create_android_log_parser;
+};
diff --git a/libmeminfo/include/meminfo/pageacct.h b/libmeminfo/include/meminfo/pageacct.h
index 8ddaef2..8483d84 100644
--- a/libmeminfo/include/meminfo/pageacct.h
+++ b/libmeminfo/include/meminfo/pageacct.h
@@ -65,5 +65,17 @@
::android::base::unique_fd pageidle_fd_;
};
+// Returns if the page present bit is set in the value
+// passed in.
+bool page_present(uint64_t pagemap_val);
+
+// Returns if the page swapped bit is set in the value
+// passed in.
+bool page_swapped(uint64_t pagemap_val);
+
+// Returns the page frame number (physical page) from
+// pagemap value
+uint64_t page_pfn(uint64_t pagemap_val);
+
} // namespace meminfo
} // namespace android
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
index 0b66074..95e5053 100644
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -73,6 +73,13 @@
const std::vector<uint16_t>& SwapOffsets();
+ // Reads /proc/<pid>/pagemap for this process for each page within
+ // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma'
+ // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks
+ // are made to see if 'vma' is *valid*.
+ // Returns false if anything goes wrong, 'true' otherwise.
+ bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap);
+
~ProcMemInfo() = default;
private:
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index a4db2f2..ccc40d1 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -121,6 +121,23 @@
EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
}
+TEST_F(ValidateProcMemInfo, TestPageMap) {
+ std::vector<uint64_t> pagemap;
+
+ auto vma_callback = [&](const Vma& vma) {
+ uint64_t* pmap_out;
+ size_t len;
+ ASSERT_EQ(0, pm_process_pagemap_range(proc, vma.start, vma.end, &pmap_out, &len));
+ ASSERT_TRUE(proc_mem->PageMap(vma, &pagemap));
+
+ EXPECT_EQ(len, ((vma.end - vma.start) / getpagesize()));
+ for (size_t i = 0; i < len; i++) {
+ EXPECT_EQ(pmap_out[i], pagemap[i]);
+ }
+ };
+ ASSERT_TRUE(proc_mem->ForEachVma(vma_callback));
+}
+
class ValidateProcMemInfoWss : public ::testing::Test {
protected:
void SetUp() override {
diff --git a/libmeminfo/pageacct.cpp b/libmeminfo/pageacct.cpp
index 887a74d..0a26c08 100644
--- a/libmeminfo/pageacct.cpp
+++ b/libmeminfo/pageacct.cpp
@@ -138,5 +138,18 @@
return !!(idle_bits & (1ULL << (pfn % 64)));
}
+// Public methods
+bool page_present(uint64_t pagemap_val) {
+ return PAGE_PRESENT(pagemap_val);
+}
+
+bool page_swapped(uint64_t pagemap_val) {
+ return PAGE_SWAPPED(pagemap_val);
+}
+
+uint64_t page_pfn(uint64_t pagemap_val) {
+ return PAGE_PFN(pagemap_val);
+}
+
} // namespace meminfo
} // namespace android
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index d6332a3..1df03b2 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -199,6 +199,33 @@
return swap_offsets_;
}
+bool ProcMemInfo::PageMap(const Vma& vma, std::vector<uint64_t>* pagemap) {
+ pagemap->clear();
+ std::string pagemap_file = ::android::base::StringPrintf("/proc/%d/pagemap", pid_);
+ ::android::base::unique_fd pagemap_fd(
+ TEMP_FAILURE_RETRY(open(pagemap_file.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (pagemap_fd < 0) {
+ PLOG(ERROR) << "Failed to open " << pagemap_file;
+ return false;
+ }
+
+ uint64_t nr_pages = (vma.end - vma.start) / getpagesize();
+ pagemap->reserve(nr_pages);
+
+ uint64_t idx = vma.start / getpagesize();
+ uint64_t last = idx + nr_pages;
+ uint64_t val;
+ for (; idx < last; idx++) {
+ if (pread64(pagemap_fd, &val, sizeof(uint64_t), idx * sizeof(uint64_t)) < 0) {
+ PLOG(ERROR) << "Failed to read page frames from page map for pid: " << pid_;
+ return false;
+ }
+ pagemap->emplace_back(val);
+ }
+
+ return true;
+}
+
bool ProcMemInfo::ReadMaps(bool get_wss) {
// Each object reads /proc/<pid>/maps only once. This is done to make sure programs that are
// running for the lifetime of the system can recycle the objects and don't have to
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index c38279d..d04a79a 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -1,10 +1,45 @@
+cc_library_headers {
+ name: "libprocessgroup_headers",
+ vendor_available: true,
+ recovery_available: true,
+ host_supported: true,
+ export_include_dirs: ["include"],
+ target: {
+ linux_bionic: {
+ enabled: true,
+ },
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
cc_library {
- srcs: ["processgroup.cpp"],
+ srcs: [
+ "processgroup.cpp",
+ "sched_policy.cpp",
+ ],
name: "libprocessgroup",
host_supported: true,
recovery_available: true,
- shared_libs: ["libbase"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+ // for cutils/android_filesystem_config.h
+ header_libs: [
+ "libcutils_headers",
+ "libprocessgroup_headers",
+ ],
export_include_dirs: ["include"],
+ export_header_lib_headers: [
+ "libprocessgroup_headers",
+ ],
cflags: [
"-Wall",
"-Werror",
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
new file mode 100644
index 0000000..79a32fd
--- /dev/null
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Check if Linux kernel enables CPUSETS feature.
+ *
+ * Return value: 1 if Linux kernel CONFIG_CPUSETS=y; 0 otherwise.
+ */
+extern bool cpusets_enabled();
+
+/*
+ * Check if Linux kernel enables SCHEDTUNE feature (only available in Android
+ * common kernel or Linaro LSK, not in mainline Linux as of v4.9)
+ *
+ * Return value: 1 if Linux kernel CONFIG_CGROUP_SCHEDTUNE=y; 0 otherwise.
+ */
+extern bool schedboost_enabled();
+
+/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
+typedef enum {
+ SP_DEFAULT = -1,
+ SP_BACKGROUND = 0,
+ SP_FOREGROUND = 1,
+ SP_SYSTEM = 2, // can't be used with set_sched_policy()
+ SP_AUDIO_APP = 3,
+ SP_AUDIO_SYS = 4,
+ SP_TOP_APP = 5,
+ SP_RT_APP = 6,
+ SP_RESTRICTED = 7,
+ SP_CNT,
+ SP_MAX = SP_CNT - 1,
+ SP_SYSTEM_DEFAULT = SP_FOREGROUND,
+} SchedPolicy;
+
+extern int set_cpuset_policy(int tid, SchedPolicy policy);
+
+/* Assign thread tid to the cgroup associated with the specified policy.
+ * If the thread is a thread group leader, that is it's gettid() == getpid(),
+ * then the other threads in the same thread group are _not_ affected.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -errno for error.
+ */
+extern int set_sched_policy(int tid, SchedPolicy policy);
+
+/* Return the policy associated with the cgroup of thread tid via policy pointer.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -1 for error and set errno.
+ */
+extern int get_sched_policy(int tid, SchedPolicy *policy);
+
+/* Return a displayable string corresponding to policy.
+ * Return value: non-NULL NUL-terminated name of unspecified length;
+ * the caller is responsible for displaying the useful part of the string.
+ */
+extern const char *get_sched_policy_name(SchedPolicy policy);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 9df8dd9..8d2ac3d 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -42,7 +42,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <private/android_filesystem_config.h>
+#include <cutils/android_filesystem_config.h>
#include <processgroup/processgroup.h>
diff --git a/libcutils/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
similarity index 99%
rename from libcutils/sched_policy.cpp
rename to libprocessgroup/sched_policy.cpp
index 3fa548f..f95d7e4 100644
--- a/libcutils/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -14,7 +14,7 @@
** limitations under the License.
*/
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
#define LOG_TAG "SchedPolicy"
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 57207de..0dd95cf 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -144,7 +144,6 @@
bool return_address_attempt = false;
bool adjust_pc = false;
- std::unique_ptr<JitDebug> jit_debug;
for (; frames_.size() < max_frames_;) {
uint64_t cur_pc = regs_->pc();
uint64_t cur_sp = regs_->sp();
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 3e8417e..fb7ca32 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -22,11 +22,13 @@
"liblog_headers",
"libsystem_headers",
"libcutils_headers",
+ "libprocessgroup_headers",
],
export_header_lib_headers: [
"liblog_headers",
"libsystem_headers",
"libcutils_headers",
+ "libprocessgroup_headers",
],
export_include_dirs: ["include"],
@@ -82,6 +84,7 @@
shared_libs: [
"libcutils",
+ "libprocessgroup",
"libdl",
"libvndksupport",
],
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 64bc402..31ca138 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -36,7 +36,7 @@
#include <utils/Log.h>
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
#if defined(__ANDROID__)
# define __android_unused
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index 903d0e2..f9ed57c 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -5,6 +5,7 @@
shared_libs: [
"libcutils",
"liblog",
+ "libprocessgroup",
],
static_libs: [
"libstatslogc",
diff --git a/logcat/Android.bp b/logcat/Android.bp
index 0543aba..5030b15 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -24,8 +24,8 @@
],
shared_libs: [
"libbase",
- "libcutils",
"libpcrecpp",
+ "libprocessgroup",
],
static_libs: ["liblog"],
logtags: ["event.logtags"],
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 87bc6ae..15e07fe 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -49,11 +49,11 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
#include <log/logprint.h>
#include <private/android_logger.h>
+#include <processgroup/sched_policy.h>
#include <system/thread_defs.h>
#include <pcrecpp.h>
diff --git a/logd/Android.bp b/logd/Android.bp
index 3abfc21..bdbdf12 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -73,6 +73,7 @@
"libcutils",
"libbase",
"libpackagelistparser",
+ "libprocessgroup",
"libcap",
],
diff --git a/logd/main.cpp b/logd/main.cpp
index 8c38d9a..fd3cdf8 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -38,12 +38,12 @@
#include <android-base/macros.h>
#include <cutils/android_get_control_file.h>
#include <cutils/properties.h>
-#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+#include <processgroup/sched_policy.h>
#include <utils/threads.h>
#include "CommandListener.h"