Merge "adb: switch install to unique_fd."
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 1592c43..9bc42e1 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -142,7 +142,7 @@
" -x: disable remote exit codes and stdout/stderr separation\n"
" emu COMMAND run emulator console command\n"
"\n"
- "app installation:\n"
+ "app installation (see also `adb shell cmd package help`):\n"
" install [-lrtsdg] [--instant] PACKAGE\n"
" push a single package to the device and install it\n"
" install-multiple [-lrtsdpg] [--instant] PACKAGE...\n"
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index bf58315..d9f2837 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -99,6 +99,11 @@
"fs_mgr_boot_config.cpp",
"fs_mgr_slotselect.cpp",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
export_include_dirs: ["include_fstab"],
header_libs: ["libbase_headers"],
}
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index 960410c..8784c94 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -53,9 +53,13 @@
$ adb disable-verity
$ adb reboot
-can be replaced with:
+*or*
- $ adb reboot -R
+ $ adb remount
+
+can be replaced in both places with:
+
+ $ adb remount -R
which will not reboot if everything is already prepared and ready
to go.
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9f6c550..785f9a2 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -954,6 +954,17 @@
std::map<std::string, std::string> device_map_;
};
+static bool IsMountPointMounted(const std::string& mount_point) {
+ // Check if this is already mounted.
+ Fstab fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+ return false;
+ }
+ auto it = std::find_if(fstab.begin(), fstab.end(),
+ [&](const auto& entry) { return entry.mount_point == mount_point; });
+ return it != fstab.end();
+}
+
// When multiple fstab records share the same mount_point, it will try to mount each
// one in turn, and ignore any duplicates after a first successful mount.
// Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
@@ -970,9 +981,18 @@
for (size_t i = 0; i < fstab->size(); i++) {
auto& current_entry = (*fstab)[i];
+ // If a filesystem should have been mounted in the first stage, we
+ // ignore it here. With one exception, if the filesystem is
+ // formattable, then it can only be formatted in the second stage,
+ // so we allow it to mount here.
+ if (current_entry.fs_mgr_flags.first_stage_mount &&
+ (!current_entry.fs_mgr_flags.formattable ||
+ IsMountPointMounted(current_entry.mount_point))) {
+ continue;
+ }
+
// Don't mount entries that are managed by vold or not for the mount mode.
if (current_entry.fs_mgr_flags.vold_managed || current_entry.fs_mgr_flags.recovery_only ||
- current_entry.fs_mgr_flags.first_stage_mount ||
((mount_mode == MOUNT_MODE_LATE) && !current_entry.fs_mgr_flags.late_mount) ||
((mount_mode == MOUNT_MODE_EARLY) && current_entry.fs_mgr_flags.late_mount)) {
continue;
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index a849578..825109f 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -378,7 +378,7 @@
D=`echo / /
echo "${D}" | grep -v /dev/root`
fi
-D=`echo "${D}" | cut -s -d' ' -f1`
+D=`echo "${D}" | cut -s -d' ' -f1 | sort -u`
D=`adb_sh df -k ${D} </dev/null`
echo "${D}"
if [ X"${D}" = X"${D##* 100[%] }" ]; then
@@ -506,7 +506,9 @@
echo "${D}" &&
echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
die "overlay takeover after remount"
- !(adb_sh grep "^overlay " /proc/mounts </dev/null | grep -v "^overlay /vendor/..* overlay ro," | grep " overlay ro,") &&
+ !(adb_sh grep "^overlay " /proc/mounts </dev/null |
+ grep -v "^overlay /\(vendor\|system\)/..* overlay ro," |
+ grep " overlay ro,") &&
!(adb_sh grep " rw," /proc/mounts </dev/null |
skip_administrative_mounts data) ||
die "remount overlayfs missed a spot (ro)"
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index a1519da..06c8176 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -26,6 +26,8 @@
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
+
+#include <algorithm>
#include <memory>
#include <android-base/file.h>
@@ -476,10 +478,16 @@
while ((entry = readdir(dir.get()))) {
const char* name = entry->d_name;
+ std::vector<String8>::iterator itIgnoreName;
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
+ itIgnoreName = find(hc->ignorePowerSupplyNames.begin(),
+ hc->ignorePowerSupplyNames.end(), String8(name));
+ if (itIgnoreName != hc->ignorePowerSupplyNames.end())
+ continue;
+
// Look for "type" file in each subdirectory
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index c01e8d7..a900071 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -22,6 +22,8 @@
#include <utils/Errors.h>
#include <utils/String8.h>
+#include <vector>
+
// periodic_chores_interval_fast, periodic_chores_interval_slow: intervals at
// which healthd wakes up to poll health state and perform periodic chores,
// in units of seconds:
@@ -71,6 +73,7 @@
int (*energyCounter)(int64_t *);
int boot_min_cap;
bool (*screen_on)(android::BatteryProperties *props);
+ std::vector<android::String8> ignorePowerSupplyNames;
};
enum EventWakeup {
diff --git a/init/README.md b/init/README.md
index 8d47e0a..3a7c71c 100644
--- a/init/README.md
+++ b/init/README.md
@@ -482,9 +482,8 @@
-f: force installation of the module even if the version of the running kernel
and the version of the kernel for which the module was compiled do not match.
-`load_all_props`
-> Loads properties from /system, /vendor, et cetera.
- This is included in the default init.rc.
+`load_system_props`
+> (This action is deprecated and no-op.)
`load_persist_props`
> Loads persistent properties when /data has been decrypted.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 4a66e46..43a520f 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -972,7 +972,7 @@
}
static Result<Success> do_load_system_props(const BuiltinArguments& args) {
- load_system_props();
+ LOG(INFO) << "deprecated action `load_system_props` called.";
return Success();
}
diff --git a/init/init.cpp b/init/init.cpp
index dc46a82..d360fdd 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -451,6 +451,8 @@
// Also, binder can't be used by recovery.
#ifndef RECOVERY
android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ android::ProcessState::self()->setCallRestriction(
+ ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY);
#endif
return Success();
}
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5328869..3199d45 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -699,22 +699,6 @@
}
}
-void property_load_boot_defaults() {
- if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
- // Try recovery path
- if (!load_properties_from_file("/prop.default", NULL)) {
- // Try legacy path
- load_properties_from_file("/default.prop", NULL);
- }
- }
- load_properties_from_file("/product/build.prop", NULL);
- load_properties_from_file("/product_services/build.prop", NULL);
- load_properties_from_file("/odm/default.prop", NULL);
- load_properties_from_file("/vendor/default.prop", NULL);
-
- update_sys_usb_config();
-}
-
static void load_override_properties() {
if (ALLOW_LOCAL_PROP_OVERRIDE) {
load_properties_from_file("/data/local.prop", NULL);
@@ -779,12 +763,29 @@
close(fd);
}
-void load_system_props() {
+void property_load_boot_defaults() {
+ // TODO(b/117892318): merge prop.default and build.prop files into one
+ // TODO(b/122864654): read the prop files from all partitions and then
+ // resolve the duplication by their origin so that RO and non-RO properties
+ // have a consistent overriding order.
+ if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
+ // Try recovery path
+ if (!load_properties_from_file("/prop.default", NULL)) {
+ // Try legacy path
+ load_properties_from_file("/default.prop", NULL);
+ }
+ }
+ load_properties_from_file("/product/build.prop", NULL);
+ load_properties_from_file("/product_services/build.prop", NULL);
+ load_properties_from_file("/odm/default.prop", NULL);
+ load_properties_from_file("/vendor/default.prop", NULL);
load_properties_from_file("/system/build.prop", NULL);
load_properties_from_file("/odm/build.prop", NULL);
load_properties_from_file("/vendor/build.prop", NULL);
load_properties_from_file("/factory/factory.prop", "ro.*");
load_recovery_id_prop();
+
+ update_sys_usb_config();
}
static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
diff --git a/init/service.cpp b/init/service.cpp
index eec55c3..f3eafe4 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -406,7 +406,7 @@
// If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
boot_clock::time_point now = boot_clock::now();
- if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
+ if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) {
if (flags_ & SVC_CRITICAL) {
diff --git a/janitors/OWNERS b/janitors/OWNERS
new file mode 100644
index 0000000..0610b41
--- /dev/null
+++ b/janitors/OWNERS
@@ -0,0 +1,4 @@
+# OWNERS file for projects that don't really have owners so much as volunteer janitors.
+enh@google.com
+hhb@google.com
+narayan@google.com
diff --git a/libmeminfo/include/meminfo/meminfo.h b/libmeminfo/include/meminfo/meminfo.h
index 5ee32d4..2fc7867 100644
--- a/libmeminfo/include/meminfo/meminfo.h
+++ b/libmeminfo/include/meminfo/meminfo.h
@@ -72,15 +72,10 @@
: start(s), end(e), offset(off), flags(f), name(n) {}
~Vma() = default;
- void clear() {
- memset(&usage, 0, sizeof(usage));
- memset(&wss, 0, sizeof(wss));
- }
+ void clear() { memset(&usage, 0, sizeof(usage)); }
// Memory usage of this mapping.
MemUsage usage;
- // Working set within this mapping.
- MemUsage wss;
};
} // namespace meminfo
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
index 0bfd80f..0b66074 100644
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -64,7 +64,12 @@
// private_dirty
// SwapPss
// All other fields of MemUsage are zeroed.
- bool SmapsOrRollup(bool use_rollup, MemUsage* stats) const;
+ bool SmapsOrRollup(MemUsage* stats) const;
+
+ // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
+ // Pss.
+ // Returns 'true' on success and the value of Pss in the out parameter.
+ bool SmapsOrRollupPss(uint64_t* pss) const;
const std::vector<uint16_t>& SwapOffsets();
@@ -82,7 +87,6 @@
std::vector<Vma> maps_;
MemUsage usage_;
- MemUsage wss_;
std::vector<uint16_t> swap_offsets_;
};
@@ -90,10 +94,21 @@
// same format as /proc/<pid>/smaps. Returns 'false' if the file is malformed.
bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback);
+// Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the
+// calling process has access to the /proc/<pid>/smaps_rollup.
+// Returns 'false' if the calling process has no permission to read the file if it exists
+// of if the file doesn't exist.
+bool IsSmapsRollupSupported(pid_t pid);
+
// Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly
// from a file. The file MUST be in the same format as /proc/<pid>/smaps
// or /proc/<pid>/smaps_rollup
bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats);
+// Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly
+// from a file and returns total Pss in kB. The file MUST be in the same format
+// as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup
+bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss);
+
} // namespace meminfo
} // namespace android
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index 20ed3bf..7d85dd2 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -284,13 +284,13 @@
EXPECT_EQ(swap_offsets.size(), 0);
}
-TEST(TestProcMemInfo, SmapsOrRollupReturn) {
- // if /proc/<pid>/smaps_rollup file exists, .SmapsRollup() must return true;
- // false otherwise
+TEST(TestProcMemInfo, IsSmapsSupportedTest) {
std::string path = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
- ProcMemInfo proc_mem(pid);
- MemUsage stats;
- EXPECT_EQ(!access(path.c_str(), F_OK), proc_mem.SmapsOrRollup(true, &stats));
+ bool supported = IsSmapsRollupSupported(pid);
+ EXPECT_EQ(!access(path.c_str(), F_OK | R_OK), supported);
+ // Second call must return what the first one returned regardless of the pid parameter.
+ // So, deliberately pass invalid pid.
+ EXPECT_EQ(supported, IsSmapsRollupSupported(-1));
}
TEST(TestProcMemInfo, SmapsOrRollupTest) {
@@ -365,6 +365,50 @@
EXPECT_EQ(stats.swap_pss, 70);
}
+TEST(TestProcMemInfo, SmapsOrRollupPssRollupTest) {
+ // This is a made up smaps for the test
+ std::string smaps =
+ R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]
+Name: [anon:dalvik-main space (region space)]
+Size: 8448 kB
+KernelPageSize: 4 kB
+MMUPageSize: 4 kB
+Rss: 2652 kB
+Pss: 2652 kB
+Shared_Clean: 840 kB
+Shared_Dirty: 40 kB
+Private_Clean: 84 kB
+Private_Dirty: 2652 kB
+Referenced: 2652 kB
+Anonymous: 2652 kB
+AnonHugePages: 0 kB
+ShmemPmdMapped: 0 kB
+Shared_Hugetlb: 0 kB
+Private_Hugetlb: 0 kB
+Swap: 102 kB
+SwapPss: 70 kB
+Locked: 2652 kB
+VmFlags: rd wr mr mw me ac
+)smaps";
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
+
+ uint64_t pss;
+ ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true);
+ EXPECT_EQ(pss, 2652);
+}
+
+TEST(TestProcMemInfo, SmapsOrRollupPssSmapsTest) {
+ std::string exec_dir = ::android::base::GetExecutableDirectory();
+ std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
+
+ uint64_t pss;
+ ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true);
+ EXPECT_EQ(pss, 19119);
+}
+
TEST(TestProcMemInfo, ForEachVmaFromFileTest) {
std::string exec_dir = ::android::base::GetExecutableDirectory();
std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
@@ -374,6 +418,9 @@
auto collect_vmas = [&](const Vma& v) { vmas.push_back(v); };
ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas));
+ // We should get a total of 6 vmas
+ ASSERT_EQ(vmas.size(), 6);
+
// Expect values to be equal to what we have in testdata1/smaps_short
// Check for sizes first
ASSERT_EQ(vmas[0].usage.vss, 32768);
@@ -468,6 +515,8 @@
auto vmas = proc_mem.Smaps(path);
ASSERT_FALSE(vmas.empty());
+ // We should get a total of 6 vmas
+ ASSERT_EQ(vmas.size(), 6);
// Expect values to be equal to what we have in testdata1/smaps_short
// Check for sizes first
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index 1f8db1a..d6332a3 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <unistd.h>
+#include <atomic>
#include <fstream>
#include <iostream>
#include <memory>
@@ -157,14 +158,14 @@
if (!get_wss_) {
LOG(WARNING) << "Trying to read process working set for " << pid_
<< " using invalid object";
- return wss_;
+ return usage_;
}
if (maps_.empty() && !ReadMaps(get_wss_)) {
LOG(ERROR) << "Failed to get working set for Process " << pid_;
}
- return wss_;
+ return usage_;
}
bool ProcMemInfo::ForEachVma(const VmaCallback& callback) {
@@ -172,11 +173,17 @@
return ForEachVmaFromFile(path, callback);
}
-bool ProcMemInfo::SmapsOrRollup(bool use_rollup, MemUsage* stats) const {
- std::string path = ::android::base::StringPrintf("/proc/%d/%s", pid_,
- use_rollup ? "smaps_rollup" : "smaps");
+bool ProcMemInfo::SmapsOrRollup(MemUsage* stats) const {
+ std::string path = ::android::base::StringPrintf(
+ "/proc/%d/%s", pid_, IsSmapsRollupSupported(pid_) ? "smaps_rollup" : "smaps");
return SmapsOrRollupFromFile(path, stats);
-};
+}
+
+bool ProcMemInfo::SmapsOrRollupPss(uint64_t* pss) const {
+ std::string path = ::android::base::StringPrintf(
+ "/proc/%d/%s", pid_, IsSmapsRollupSupported(pid_) ? "smaps_rollup" : "smaps");
+ return SmapsOrRollupPssFromFile(path, pss);
+}
const std::vector<uint16_t>& ProcMemInfo::SwapOffsets() {
if (get_wss_) {
@@ -228,11 +235,7 @@
maps_.clear();
return false;
}
- if (get_wss) {
- add_mem_usage(&wss_, vma.wss);
- } else {
- add_mem_usage(&usage_, vma.usage);
- }
+ add_mem_usage(&usage_, vma.usage);
}
return true;
@@ -300,31 +303,20 @@
// 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.wss.vss += pagesz;
- vma.wss.rss += pagesz;
- vma.wss.uss += is_private ? pagesz : 0;
- vma.wss.pss += pagesz / pg_counts[i];
- if (is_private) {
- vma.wss.private_dirty += is_dirty ? pagesz : 0;
- vma.wss.private_clean += is_dirty ? 0 : pagesz;
- } else {
- vma.wss.shared_dirty += is_dirty ? pagesz : 0;
- vma.wss.shared_clean += is_dirty ? 0 : pagesz;
- }
+ vma.usage.vss += pagesz;
+ }
+
+ vma.usage.rss += pagesz;
+ vma.usage.uss += is_private ? pagesz : 0;
+ vma.usage.pss += pagesz / pg_counts[i];
+ if (is_private) {
+ vma.usage.private_dirty += is_dirty ? pagesz : 0;
+ vma.usage.private_clean += is_dirty ? 0 : pagesz;
} else {
- vma.usage.rss += pagesz;
- vma.usage.uss += is_private ? pagesz : 0;
- vma.usage.pss += pagesz / pg_counts[i];
- if (is_private) {
- vma.usage.private_dirty += is_dirty ? pagesz : 0;
- vma.usage.private_clean += is_dirty ? 0 : pagesz;
- } else {
- vma.usage.shared_dirty += is_dirty ? pagesz : 0;
- vma.usage.shared_clean += is_dirty ? 0 : pagesz;
- }
+ vma.usage.shared_dirty += is_dirty ? pagesz : 0;
+ vma.usage.shared_clean += is_dirty ? 0 : pagesz;
}
}
-
return true;
}
@@ -338,8 +330,9 @@
char* line = nullptr;
bool parsing_vma = false;
ssize_t line_len;
+ size_t line_alloc = 0;
Vma vma;
- while ((line_len = getline(&line, 0, fp.get())) > 0) {
+ while ((line_len = getline(&line, &line_alloc, fp.get())) > 0) {
// Make sure the line buffer terminates like a C string for ReadMapFile
line[line_len] = '\0';
@@ -382,15 +375,41 @@
return true;
}
+enum smaps_rollup_support { UNTRIED, SUPPORTED, UNSUPPORTED };
+
+static std::atomic<smaps_rollup_support> g_rollup_support = UNTRIED;
+
+bool IsSmapsRollupSupported(pid_t pid) {
+ // Similar to OpenSmapsOrRollup checks from android_os_Debug.cpp, except
+ // the method only checks if rollup is supported and returns the status
+ // right away.
+ enum smaps_rollup_support rollup_support = g_rollup_support.load(std::memory_order_relaxed);
+ if (rollup_support != UNTRIED) {
+ return rollup_support == SUPPORTED;
+ }
+ std::string rollup_file = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
+ if (access(rollup_file.c_str(), F_OK | R_OK)) {
+ // No check for errno = ENOENT necessary here. The caller MUST fallback to
+ // using /proc/<pid>/smaps instead anyway.
+ g_rollup_support.store(UNSUPPORTED, std::memory_order_relaxed);
+ return false;
+ }
+
+ g_rollup_support.store(SUPPORTED, std::memory_order_relaxed);
+ LOG(INFO) << "Using smaps_rollup for pss collection";
+ return true;
+}
+
bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats) {
auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
if (fp == nullptr) {
return false;
}
- char line[1024];
+ char* line = nullptr;
+ size_t line_alloc = 0;
stats->clear();
- while (fgets(line, sizeof(line), fp.get()) != nullptr) {
+ while (getline(&line, &line_alloc, fp.get()) > 0) {
switch (line[0]) {
case 'P':
if (strncmp(line, "Pss:", 4) == 0) {
@@ -423,6 +442,28 @@
}
}
+ // free getline() managed buffer
+ free(line);
+ return true;
+}
+
+bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss) {
+ auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
+ if (fp == nullptr) {
+ return false;
+ }
+ *pss = 0;
+ char* line = nullptr;
+ size_t line_alloc = 0;
+ while (getline(&line, &line_alloc, fp.get()) > 0) {
+ uint64_t v;
+ if (sscanf(line, "Pss: %" SCNu64 " kB", &v) == 1) {
+ *pss += v;
+ }
+ }
+
+ // free getline() managed buffer
+ free(line);
return true;
}
diff --git a/libmeminfo/tools/procmem.cpp b/libmeminfo/tools/procmem.cpp
index b9b174d..47881ed 100644
--- a/libmeminfo/tools/procmem.cpp
+++ b/libmeminfo/tools/procmem.cpp
@@ -98,7 +98,7 @@
std::stringstream ss;
print_header(ss);
for (auto& vma : maps) {
- const MemUsage& vma_stats = show_wss ? vma.wss : vma.usage;
+ const MemUsage& vma_stats = vma.usage;
if (hide_zeroes && vma_stats.rss == 0) {
continue;
}
@@ -116,14 +116,14 @@
int main(int argc, char* argv[]) {
int opt;
auto pss_sort = [](const Vma& a, const Vma& b) {
- uint64_t pss_a = show_wss ? a.wss.pss : a.usage.pss;
- uint64_t pss_b = show_wss ? b.wss.pss : b.usage.pss;
+ uint64_t pss_a = a.usage.pss;
+ uint64_t pss_b = b.usage.pss;
return pss_a > pss_b;
};
auto uss_sort = [](const Vma& a, const Vma& b) {
- uint64_t uss_a = show_wss ? a.wss.uss : a.usage.uss;
- uint64_t uss_b = show_wss ? b.wss.uss : b.usage.uss;
+ uint64_t uss_a = a.usage.uss;
+ uint64_t uss_b = b.usage.uss;
return uss_a > uss_b;
};
@@ -182,7 +182,7 @@
}
ProcMemInfo proc(pid, show_wss);
- const MemUsage& proc_stats = show_wss ? proc.Wss() : proc.Usage();
+ const MemUsage& proc_stats = proc.Usage();
std::vector<Vma> maps(proc.Maps());
if (sort_func != nullptr) {
std::sort(maps.begin(), maps.end(), sort_func);
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp
index a751722..21a684c 100644
--- a/libmeminfo/tools/procrank.cpp
+++ b/libmeminfo/tools/procrank.cpp
@@ -465,7 +465,7 @@
}
// Skip processes with no memory mappings
- uint64_t vss = show_wss ? proc.Wss().vss : proc.Usage().vss;
+ uint64_t vss = proc.Usage().vss;
if (vss == 0) return true;
// collect swap_offset counts from all processes in 1st pass
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 92fd2a2..c54570e 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -17,6 +17,20 @@
"liblog",
],
+ target: {
+ android: {
+ version_script: "libnativebridge.map.txt",
+ },
+ linux: {
+ version_script: "libnativebridge.map.txt",
+ },
+ },
+
+ stubs: {
+ symbol_file: "libnativebridge.map.txt",
+ versions: ["1"],
+ },
+
export_include_dirs: ["include"],
cflags: [
diff --git a/libnativebridge/OWNERS b/libnativebridge/OWNERS
index f2cc942..6f0824b 100644
--- a/libnativebridge/OWNERS
+++ b/libnativebridge/OWNERS
@@ -1 +1,2 @@
dimitry@google.com
+eaeltsin@google.com
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
index 28f1927..5aea967 100644
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ b/libnativebridge/include/nativebridge/native_bridge.h
@@ -17,12 +17,17 @@
#ifndef NATIVE_BRIDGE_H_
#define NATIVE_BRIDGE_H_
-#include "jni.h"
#include <signal.h>
+#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
+#include "jni.h"
+
+#ifdef __cplusplus
namespace android {
+extern "C" {
+#endif // __cplusplus
struct NativeBridgeRuntimeCallbacks;
struct NativeBridgeRuntimeValues;
@@ -32,11 +37,10 @@
// to the chain.
typedef bool (*NativeBridgeSignalHandlerFn)(int, siginfo_t*, void*);
-
// Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
// signals that we do not want to load a native bridge.
bool LoadNativeBridge(const char* native_bridge_library_filename,
- const NativeBridgeRuntimeCallbacks* runtime_callbacks);
+ const struct NativeBridgeRuntimeCallbacks* runtime_callbacks);
// Quick check whether a native bridge will be needed. This is based off of the instruction set
// of the process.
@@ -138,19 +142,17 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
-native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
- const char* ld_library_path,
- const char* default_library_path,
- uint64_t type,
- const char* permitted_when_isolated_path,
- native_bridge_namespace_t* parent_ns);
+struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
+ const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
+ const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns);
// Creates a link which shares some libraries from one namespace to another.
// NativeBridge's peer of android_link_namespaces() of dynamic linker.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
-bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
+bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
+ struct native_bridge_namespace_t* to,
const char* shared_libs_sonames);
// Load a shared library with namespace key that is supported by the native bridge.
@@ -159,10 +161,11 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns);
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
+ struct native_bridge_namespace_t* ns);
// Returns vendor namespace if it is enabled for the device and null otherwise
-native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
+struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
// Native bridge interfaces to runtime.
struct NativeBridgeCallbacks {
@@ -177,8 +180,8 @@
// runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
// Returns:
// true if initialization was successful.
- bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
- const char* instruction_set);
+ bool (*initialize)(const struct NativeBridgeRuntimeCallbacks* runtime_cbs,
+ const char* private_dir, const char* instruction_set);
// Load a shared library that is supported by the native bridge.
//
@@ -314,12 +317,12 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
- native_bridge_namespace_t* (*createNamespace)(const char* name,
- const char* ld_library_path,
- const char* default_library_path,
- uint64_t type,
- const char* permitted_when_isolated_path,
- native_bridge_namespace_t* parent_ns);
+ struct native_bridge_namespace_t* (*createNamespace)(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ struct native_bridge_namespace_t* parent_ns);
// Creates a link which shares some libraries from one namespace to another.
// NativeBridge's peer of android_link_namespaces() of dynamic linker.
@@ -334,8 +337,8 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
- bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
- const char* shared_libs_sonames);
+ bool (*linkNamespaces)(struct native_bridge_namespace_t* from,
+ struct native_bridge_namespace_t* to, const char* shared_libs_sonames);
// Load a shared library within a namespace.
// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
@@ -350,7 +353,7 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use loadLibrary instead in non-namespace scenario.
- void* (*loadLibraryExt)(const char* libpath, int flag, native_bridge_namespace_t* ns);
+ void* (*loadLibraryExt)(const char* libpath, int flag, struct native_bridge_namespace_t* ns);
// Get native bridge version of vendor namespace.
// The vendor namespace is the namespace used to load vendor public libraries.
@@ -359,7 +362,7 @@
//
// Returns:
// vendor namespace or null if it was not set up for the device
- native_bridge_namespace_t* (*getVendorNamespace)();
+ struct native_bridge_namespace_t* (*getVendorNamespace)();
};
// Runtime interfaces to native bridge.
@@ -396,6 +399,9 @@
uint32_t method_count);
};
-}; // namespace android
+#ifdef __cplusplus
+} // extern "C"
+} // namespace android
+#endif // __cplusplus
#endif // NATIVE_BRIDGE_H_
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
new file mode 100644
index 0000000..a616b85
--- /dev/null
+++ b/libnativebridge/libnativebridge.map.txt
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2019 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.
+#
+
+# TODO(b/122710865): Most of these uses come from libnativeloader, which should be bundled
+# together with libnativebridge in the APEX. Once this happens, prune this list.
+LIBNATIVEBRIDGE_1 {
+ global:
+ NativeBridgeIsSupported;
+ NativeBridgeLoadLibrary;
+ NativeBridgeUnloadLibrary;
+ NativeBridgeGetError;
+ NativeBridgeIsPathSupported;
+ NativeBridgeCreateNamespace;
+ NativeBridgeGetVendorNamespace;
+ NativeBridgeLinkNamespaces;
+ NativeBridgeLoadLibraryExt;
+ NativeBridgeInitAnonymousNamespace;
+ NativeBridgeInitialized;
+ NativeBridgeGetTrampoline;
+ LoadNativeBridge;
+ PreInitializeNativeBridge;
+ InitializeNativeBridge;
+ NativeBridgeGetVersion;
+ NativeBridgeGetSignalHandler;
+ UnloadNativeBridge;
+ NativeBridgeAvailable;
+ NeedsNativeBridge;
+ NativeBridgeError;
+ NativeBridgeNameAcceptable;
+ local:
+ *;
+};
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index e24307a..a2d8d81 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -33,6 +33,13 @@
namespace android {
+#ifdef __APPLE__
+template <typename T>
+void UNUSED(const T&) {}
+#endif
+
+extern "C" {
+
// Environment values required by the apps running with native bridge.
struct NativeBridgeRuntimeValues {
const char* os_arch;
@@ -252,10 +259,6 @@
return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
}
-#ifdef __APPLE__
-template<typename T> void UNUSED(const T&) {}
-#endif
-
bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
if (state != NativeBridgeState::kOpened) {
ALOGE("Invalid state: native bridge is expected to be opened.");
@@ -626,4 +629,6 @@
return nullptr;
}
-}; // namespace android
+} // extern "C"
+
+} // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index 222bc4c..744a4a8 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -86,3 +86,14 @@
],
header_libs: ["libbase_headers"],
}
+
+// Build the test for the C API.
+cc_test {
+ name: "libnativebridge-api-tests",
+ host_supported: true,
+ test_per_src: true,
+ srcs: [
+ "NativeBridgeApi.c",
+ ],
+ header_libs: ["libnativebridge-dummy-headers"],
+}
diff --git a/libnativebridge/tests/NativeBridgeApi.c b/libnativebridge/tests/NativeBridgeApi.c
new file mode 100644
index 0000000..7ab71fe
--- /dev/null
+++ b/libnativebridge/tests/NativeBridgeApi.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/* The main purpose of this test is to ensure this C header compiles in C, so
+ * that no C++ features inadvertently leak into the C ABI. */
+#include "nativebridge/native_bridge.h"
+
+int main(int argc, char** argv) {
+ (void)argc;
+ (void)argv;
+ return 0;
+}
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 89d4fc0..e267f58 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -221,7 +221,6 @@
"liblog",
"liblzma",
"libunwindstack",
- "libdexfile",
"libdexfile_support",
],
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 21ca47b..0149a42 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -21,7 +21,6 @@
#include <unordered_map>
#include <android-base/file.h>
-#include <dex/dex_file.h>
#include <gtest/gtest.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
@@ -40,17 +39,15 @@
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
- static_cast<size_t>(
- TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
+ ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
// Header too small.
EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
// Header correct, file too small.
ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
- ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
- tf.fd, kDexData, sizeof(art::DexFile::Header)))));
+ ASSERT_EQ(sizeof(kDexData) - 1,
+ static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
}
@@ -78,7 +75,7 @@
TEST(DexFileTest, from_memory_fail_too_small_for_header) {
MemoryFake memory;
- memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
+ memory.SetMemory(0x1000, kDexData, 10);
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
}
@@ -187,15 +184,6 @@
ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
EXPECT_EQ("Main.main", method);
EXPECT_EQ(0U, method_offset);
-
- // Make sure that any data that is cached is still retrievable.
- ASSERT_TRUE(dex_file->GetMethodInformation(0x104, &method, &method_offset));
- EXPECT_EQ("Main.<init>", method);
- EXPECT_EQ(4U, method_offset);
-
- ASSERT_TRUE(dex_file->GetMethodInformation(0x119, &method, &method_offset));
- EXPECT_EQ("Main.main", method);
- EXPECT_EQ(1U, method_offset);
}
TEST(DexFileTest, get_method_empty) {
@@ -210,12 +198,6 @@
EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-
- // Make sure that once the whole dex file has been cached, no problems occur.
- EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-
- // Choose a value that is in the cached map, but not in a valid method.
- EXPECT_FALSE(dex_file->GetMethodInformation(0x110, &method, &method_offset));
}
} // namespace unwindstack
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 7794f81..ca78c38 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -16,6 +16,7 @@
#define LOG_TAG "lowmemorykiller"
+#include <dirent.h>
#include <errno.h>
#include <inttypes.h>
#include <pwd.h>
@@ -28,18 +29,22 @@
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/mman.h>
+#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/sysinfo.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <cutils/properties.h>
+#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <lmkd.h>
#include <log/log.h>
#include <log/log_event_list.h>
#include <log/log_time.h>
+#include <system/thread_defs.h>
#ifdef LMKD_LOG_STATS
#include "statslog.h"
@@ -1261,6 +1266,41 @@
return maxprocp;
}
+static void set_process_group_and_prio(int pid, SchedPolicy sp, int prio) {
+ DIR* d;
+ char proc_path[PATH_MAX];
+ struct dirent* de;
+
+ snprintf(proc_path, sizeof(proc_path), "/proc/%d/task", pid);
+ if (!(d = opendir(proc_path))) {
+ ALOGW("Failed to open %s; errno=%d: process pid(%d) might have died", proc_path, errno,
+ pid);
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ int t_pid;
+
+ if (de->d_name[0] == '.') continue;
+ t_pid = atoi(de->d_name);
+
+ if (!t_pid) {
+ ALOGW("Failed to get t_pid for '%s' of pid(%d)", de->d_name, pid);
+ continue;
+ }
+
+ if (setpriority(PRIO_PROCESS, t_pid, prio) && errno != ESRCH) {
+ ALOGW("Unable to raise priority of killing t_pid (%d): errno=%d", t_pid, errno);
+ }
+
+ if (set_cpuset_policy(t_pid, sp)) {
+ ALOGW("Failed to set_cpuset_policy on pid(%d) t_pid(%d) to %d", pid, t_pid, (int)sp);
+ continue;
+ }
+ }
+ closedir(d);
+}
+
static int last_killed_pid = -1;
/* Kill one process specified by procp. Returns the size of the process killed */
@@ -1301,6 +1341,9 @@
/* CAP_KILL required */
r = kill(pid, SIGKILL);
+
+ set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
+
inc_killcnt(procp->oomadj);
ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
taskname, pid, uid, procp->oomadj, tasksize * page_k);
diff --git a/lmkd/tests/Android.bp b/lmkd/tests/Android.bp
index cbf44e9..4e845fd 100644
--- a/lmkd/tests/Android.bp
+++ b/lmkd/tests/Android.bp
@@ -18,6 +18,7 @@
shared_libs: [
"libbase",
"liblog",
+ "libcutils",
],
static_libs: [
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b34399d..9b20964 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -346,12 +346,6 @@
trigger boot
on post-fs
- # Load properties from
- # /system/build.prop,
- # /odm/build.prop,
- # /vendor/build.prop and
- # /factory/factory.prop
- load_system_props
start vold
exec - system system -- /system/bin/vdc checkpoint markBootAttempt