Merge "Look for radio.img and bootloader.img in ANDROID_PRODUCT_OUT" into main
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 6a19878..12ba502 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -148,7 +148,7 @@
noinline void leak() {
while (true) {
void* mapping =
- mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
static_cast<volatile char*>(mapping)[0] = 'a';
}
}
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 4cd6193..52c1c25 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -300,24 +300,7 @@
}
static void ConsumeFd(unique_fd fd, std::string* output) {
- constexpr size_t read_length = PAGE_SIZE;
- std::string result;
-
- while (true) {
- size_t offset = result.size();
- result.resize(result.size() + PAGE_SIZE);
- ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &result[offset], read_length));
- if (rc == -1) {
- FAIL() << "read failed: " << strerror(errno);
- } else if (rc == 0) {
- result.resize(result.size() - PAGE_SIZE);
- break;
- }
-
- result.resize(result.size() - PAGE_SIZE + rc);
- }
-
- *output = std::move(result);
+ ASSERT_TRUE(android::base::ReadFdToString(fd, output));
}
class LogcatCollector {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c6a535a..1e5365d 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -721,19 +721,19 @@
}
size_t thread_stack_pages = 8;
- void* thread_stack_allocation = mmap(nullptr, PAGE_SIZE * (thread_stack_pages + 2), PROT_NONE,
+ void* thread_stack_allocation = mmap(nullptr, getpagesize() * (thread_stack_pages + 2), PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (thread_stack_allocation == MAP_FAILED) {
fatal_errno("failed to allocate debuggerd thread stack");
}
- char* stack = static_cast<char*>(thread_stack_allocation) + PAGE_SIZE;
- if (mprotect(stack, PAGE_SIZE * thread_stack_pages, PROT_READ | PROT_WRITE) != 0) {
+ char* stack = static_cast<char*>(thread_stack_allocation) + getpagesize();
+ if (mprotect(stack, getpagesize() * thread_stack_pages, PROT_READ | PROT_WRITE) != 0) {
fatal_errno("failed to mprotect debuggerd thread stack");
}
// Stack grows negatively, set it to the last byte in the page...
- stack = (stack + thread_stack_pages * PAGE_SIZE - 1);
+ stack = (stack + thread_stack_pages * getpagesize() - 1);
// and align it.
stack -= 15;
pseudothread_stack = stack;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 5a62fe1..837f406 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -22,6 +22,7 @@
#include <android-base/macros.h>
#include <bionic/macros.h>
+#include <unistd.h>
#include "tombstone.pb.h"
@@ -54,21 +55,21 @@
}
untagged_fault_addr_ = process_info.untagged_fault_address;
- uintptr_t fault_page = untagged_fault_addr_ & ~(PAGE_SIZE - 1);
+ uintptr_t fault_page = untagged_fault_addr_ & ~(getpagesize() - 1);
- uintptr_t memory_begin = fault_page - PAGE_SIZE * 16;
+ uintptr_t memory_begin = fault_page - getpagesize() * 16;
if (memory_begin > fault_page) {
return;
}
- uintptr_t memory_end = fault_page + PAGE_SIZE * 16;
+ uintptr_t memory_end = fault_page + getpagesize() * 16;
if (memory_end < fault_page) {
return;
}
auto memory = std::make_unique<char[]>(memory_end - memory_begin);
- for (auto i = memory_begin; i != memory_end; i += PAGE_SIZE) {
- process_memory->ReadFully(i, memory.get() + i - memory_begin, PAGE_SIZE);
+ for (auto i = memory_begin; i != memory_end; i += getpagesize()) {
+ process_memory->ReadFully(i, memory.get() + i - memory_begin, getpagesize());
}
auto memory_tags = std::make_unique<char[]>((memory_end - memory_begin) / kTagGranuleSize);
diff --git a/debuggerd/rust/tombstoned_client/src/lib.rs b/debuggerd/rust/tombstoned_client/src/lib.rs
index 5c8abef..d1b5e69 100644
--- a/debuggerd/rust/tombstoned_client/src/lib.rs
+++ b/debuggerd/rust/tombstoned_client/src/lib.rs
@@ -39,20 +39,26 @@
}
impl TombstonedConnection {
+ /// # Safety
+ ///
+ /// The file descriptors must be valid and open.
unsafe fn from_raw_fds(
tombstoned_socket: RawFd,
text_output_fd: RawFd,
proto_output_fd: RawFd,
) -> Self {
Self {
- tombstoned_socket: File::from_raw_fd(tombstoned_socket),
+ // SAFETY: The caller guarantees that the file descriptor is valid and open.
+ tombstoned_socket: unsafe { File::from_raw_fd(tombstoned_socket) },
text_output: if text_output_fd >= 0 {
- Some(File::from_raw_fd(text_output_fd))
+ // SAFETY: The caller guarantees that the file descriptor is valid and open.
+ Some(unsafe { File::from_raw_fd(text_output_fd) })
} else {
None
},
proto_output: if proto_output_fd >= 0 {
- Some(File::from_raw_fd(proto_output_fd))
+ // SAFETY: The caller guarantees that the file descriptor is valid and open.
+ Some(unsafe { File::from_raw_fd(proto_output_fd) })
} else {
None
},
@@ -71,6 +77,8 @@
&mut proto_output_fd,
dump_type,
) {
+ // SAFETY: If tombstoned_connect_files returns successfully then they file descriptors
+ // are valid and open.
Ok(unsafe { Self::from_raw_fds(tombstoned_socket, text_output_fd, proto_output_fd) })
} else {
Err(Error)
@@ -146,8 +154,6 @@
.write_all(b"test data")
.expect("Failed to write to text output FD.");
- connection
- .notify_completion()
- .expect("Failed to notify completion.");
+ connection.notify_completion().expect("Failed to notify completion.");
}
}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 1ce4e8b..2dae1ab 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -76,6 +76,7 @@
#include "constants.h"
#include "diagnose_usb.h"
#include "fastboot_driver.h"
+#include "fastboot_driver_interface.h"
#include "fs.h"
#include "storage.h"
#include "super_flash_helper.h"
@@ -177,7 +178,7 @@
// clang-format on
};
-static char* get_android_product_out() {
+char* get_android_product_out() {
char* dir = getenv("ANDROID_PRODUCT_OUT");
if (dir == nullptr || dir[0] == '\0') {
return nullptr;
@@ -1000,7 +1001,7 @@
return resparse_file(s.get(), max_size);
}
-static uint64_t get_uint_var(const char* var_name) {
+static uint64_t get_uint_var(const char* var_name, fastboot::IFastBootDriver* fb) {
std::string value_str;
if (fb->GetVar(var_name, &value_str) != fastboot::SUCCESS || value_str.empty()) {
verbose("target didn't report %s", var_name);
@@ -1025,7 +1026,7 @@
// Unlimited, so see what the target device's limit is.
// TODO: shouldn't we apply this limit even if you've used -S?
if (target_sparse_limit == -1) {
- target_sparse_limit = static_cast<int64_t>(get_uint_var("max-download-size"));
+ target_sparse_limit = static_cast<int64_t>(get_uint_var("max-download-size", fp->fb));
}
if (target_sparse_limit > 0) {
limit = target_sparse_limit;
@@ -1414,7 +1415,7 @@
}
}
-bool is_retrofit_device() {
+bool is_retrofit_device(fastboot::IFastBootDriver* fb) {
std::string value;
if (fb->GetVar("super-partition-name", &value) != fastboot::SUCCESS) {
return false;
@@ -1424,8 +1425,9 @@
// Fetch a partition from the device to a given fd. This is a wrapper over FetchToFd to fetch
// the full image.
-static uint64_t fetch_partition(const std::string& partition, borrowed_fd fd) {
- uint64_t fetch_size = get_uint_var(FB_VAR_MAX_FETCH_SIZE);
+static uint64_t fetch_partition(const std::string& partition, borrowed_fd fd,
+ fastboot::IFastBootDriver* fb) {
+ uint64_t fetch_size = get_uint_var(FB_VAR_MAX_FETCH_SIZE, fb);
if (fetch_size == 0) {
die("Unable to get %s. Device does not support fetch command.", FB_VAR_MAX_FETCH_SIZE);
}
@@ -1447,17 +1449,18 @@
}
static void do_fetch(const std::string& partition, const std::string& slot_override,
- const std::string& outfile) {
+ const std::string& outfile, fastboot::IFastBootDriver* fb) {
unique_fd fd(TEMP_FAILURE_RETRY(
open(outfile.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, 0644)));
- auto fetch = std::bind(fetch_partition, _1, borrowed_fd(fd));
+ auto fetch = std::bind(fetch_partition, _1, borrowed_fd(fd), fb);
do_for_partitions(partition, slot_override, fetch, false /* force slot */);
}
// Return immediately if not flashing a vendor boot image. If flashing a vendor boot image,
// repack vendor_boot image with an updated ramdisk. After execution, buf is set
// to the new image to flash, and return value is the real partition name to flash.
-static std::string repack_ramdisk(const char* pname, struct fastboot_buffer* buf) {
+static std::string repack_ramdisk(const char* pname, struct fastboot_buffer* buf,
+ fastboot::IFastBootDriver* fb) {
std::string_view pname_sv{pname};
if (!android::base::StartsWith(pname_sv, "vendor_boot:") &&
@@ -1475,7 +1478,7 @@
std::string ramdisk(pname_sv.substr(pname_sv.find(':') + 1));
unique_fd vendor_boot(make_temporary_fd("vendor boot repack"));
- uint64_t vendor_boot_size = fetch_partition(partition, vendor_boot);
+ uint64_t vendor_boot_size = fetch_partition(partition, vendor_boot, fb);
auto repack_res = replace_vendor_ramdisk(vendor_boot, vendor_boot_size, ramdisk, buf->fd,
static_cast<uint64_t>(buf->sz));
if (!repack_res.ok()) {
@@ -1490,10 +1493,13 @@
void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
const FlashingPlan* fp) {
+ if (!fp) {
+ die("do flash was called without a valid flashing plan");
+ }
verbose("Do flash %s %s", pname, fname);
struct fastboot_buffer buf;
- if (fp && fp->source) {
+ if (fp->source) {
unique_fd fd = fp->source->OpenFile(fname);
if (fd < 0 || !load_buf_fd(std::move(fd), &buf, fp)) {
die("could not load '%s': %s", fname, strerror(errno));
@@ -1512,7 +1518,7 @@
if (is_logical(pname)) {
fb->ResizePartition(pname, std::to_string(buf.image_size));
}
- std::string flash_pname = repack_ramdisk(pname, &buf);
+ std::string flash_pname = repack_ramdisk(pname, &buf, fp->fb);
flash_buf(flash_pname, &buf, apply_vbmeta);
}
@@ -1751,7 +1757,7 @@
}
tasks.emplace_back(std::move(task));
}
- if (auto flash_super_task = FlashSuperLayoutTask::InitializeFromTasks(fp, tasks)) {
+ if (auto flash_super_task = OptimizedFlashSuperTask::InitializeFromTasks(fp, tasks)) {
auto it = tasks.begin();
for (size_t i = 0; i < tasks.size(); i++) {
if (auto flash_task = tasks[i]->AsFlashTask()) {
@@ -1791,13 +1797,25 @@
CancelSnapshotIfNeeded();
- tasks_ = CollectTasksFromImageList();
+ tasks_ = CollectTasks();
for (auto& task : tasks_) {
task->Run();
}
return;
}
+std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasks() {
+ std::vector<std::unique_ptr<Task>> tasks;
+ if (fp_->should_use_fastboot_info) {
+ tasks = CollectTasksFromFastbootInfo();
+
+ } else {
+ tasks = CollectTasksFromImageList();
+ }
+
+ return tasks;
+}
+
void FlashAllTool::CheckRequirements() {
std::vector<char> contents;
if (!fp_->source->ReadFile("android-info.txt", &contents)) {
@@ -1852,8 +1870,7 @@
// or in bootloader fastboot.
std::vector<std::unique_ptr<Task>> tasks;
AddFlashTasks(boot_images_, tasks);
-
- if (auto flash_super_task = FlashSuperLayoutTask::Initialize(fp_, os_images_)) {
+ if (auto flash_super_task = OptimizedFlashSuperTask::Initialize(fp_, os_images_)) {
tasks.emplace_back(std::move(flash_super_task));
} else {
// Sync the super partition. This will reboot to userspace fastboot if needed.
@@ -1865,7 +1882,7 @@
// On these devices, secondary slots must be flashed as physical
// partitions (otherwise they would not mount on first boot). To enforce
// this, we delete any logical partitions for the "other" slot.
- if (is_retrofit_device()) {
+ if (is_retrofit_device(fp_->fb)) {
std::string partition_name = image->part_name + "_"s + slot;
if (image->IsSecondary() && should_flash_in_userspace(partition_name)) {
fp_->fb->DeletePartition(partition_name);
@@ -1875,10 +1892,23 @@
tasks.emplace_back(std::make_unique<ResizeTask>(fp_, image->part_name, "0", slot));
}
}
+
AddFlashTasks(os_images_, tasks);
return tasks;
}
+std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasksFromFastbootInfo() {
+ std::vector<std::unique_ptr<Task>> tasks;
+ std::vector<char> contents;
+ if (!fp_->source->ReadFile("fastboot-info.txt", &contents)) {
+ LOG(VERBOSE) << "Flashing from hardcoded images. fastboot-info.txt is empty or does not "
+ "exist";
+ return CollectTasksFromImageList();
+ }
+ tasks = ParseFastbootInfo(fp_, Split({contents.data(), contents.size()}, "\n"));
+ return tasks;
+}
+
void FlashAllTool::AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
std::vector<std::unique_ptr<Task>>& tasks) {
for (const auto& [image, slot] : images) {
@@ -2187,6 +2217,7 @@
{"disable-verification", no_argument, 0, 0},
{"disable-verity", no_argument, 0, 0},
{"disable-super-optimization", no_argument, 0, 0},
+ {"disable-fastboot-info", no_argument, 0, 0},
{"force", no_argument, 0, 0},
{"fs-options", required_argument, 0, 0},
{"header-version", required_argument, 0, 0},
@@ -2209,8 +2240,9 @@
{0, 0, 0, 0}};
serial = getenv("FASTBOOT_DEVICE");
- if (!serial)
+ if (!serial) {
serial = getenv("ANDROID_SERIAL");
+ }
int c;
while ((c = getopt_long(argc, argv, "a::hls:S:vw", longopts, &longindex)) != -1) {
@@ -2226,6 +2258,8 @@
g_disable_verity = true;
} else if (name == "disable-super-optimization") {
fp->should_optimize_flash_super = false;
+ } else if (name == "disable-fastboot-info") {
+ fp->should_use_fastboot_info = false;
} else if (name == "force") {
fp->force_flash = true;
} else if (name == "fs-options") {
@@ -2555,7 +2589,7 @@
} else if (command == FB_CMD_FETCH) {
std::string partition = next_arg(&args);
std::string outfile = next_arg(&args);
- do_fetch(partition, fp->slot_override, outfile);
+ do_fetch(partition, fp->slot_override, outfile, fp->fb);
} else {
syntax_error("unknown command %s", command.c_str());
}
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 196bd67..f6ffb64 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -97,6 +97,7 @@
bool skip_secondary = false;
bool force_flash = false;
bool should_optimize_flash_super = true;
+ bool should_use_fastboot_info = true;
uint64_t sparse_limit = 0;
std::string slot_override;
@@ -111,6 +112,7 @@
FlashAllTool(FlashingPlan* fp);
void Flash();
+ std::vector<std::unique_ptr<Task>> CollectTasks();
private:
void CheckRequirements();
@@ -118,6 +120,8 @@
void CollectImages();
void AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
std::vector<std::unique_ptr<Task>>& tasks);
+
+ std::vector<std::unique_ptr<Task>> CollectTasksFromFastbootInfo();
std::vector<std::unique_ptr<Task>> CollectTasksFromImageList();
std::vector<ImageEntry> boot_images_;
@@ -143,6 +147,7 @@
unique_fd OpenFile(const std::string& name) const override;
};
+char* get_android_product_out();
bool should_flash_in_userspace(const std::string& partition_name);
bool is_userspace_fastboot();
void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
@@ -182,7 +187,7 @@
int64_t get_sparse_limit(int64_t size, const FlashingPlan* fp);
std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size);
-bool is_retrofit_device();
+bool is_retrofit_device(fastboot::IFastBootDriver* fb);
bool is_logical(const std::string& partition);
void fb_perform_format(const std::string& partition, int skip_if_not_supported,
const std::string& type_override, const std::string& size_override,
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 6ac26ce..8774ead 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -105,7 +105,7 @@
std::vector<std::string>* info = nullptr);
RetCode FetchToFd(const std::string& partition, android::base::borrowed_fd fd,
int64_t offset = -1, int64_t size = -1, std::string* response = nullptr,
- std::vector<std::string>* info = nullptr);
+ std::vector<std::string>* info = nullptr) override;
/* HIGHER LEVEL COMMANDS -- Composed of the commands above */
RetCode FlashPartition(const std::string& partition, const std::vector<char>& data);
diff --git a/fastboot/fastboot_driver_interface.h b/fastboot/fastboot_driver_interface.h
index 795938f..7cb8a6b 100644
--- a/fastboot/fastboot_driver_interface.h
+++ b/fastboot/fastboot_driver_interface.h
@@ -45,6 +45,10 @@
std::vector<std::string>* info = nullptr) = 0;
RetCode virtual GetVar(const std::string& key, std::string* val,
std::vector<std::string>* info = nullptr) = 0;
+ RetCode virtual FetchToFd(const std::string& partition, android::base::borrowed_fd fd,
+ int64_t offset = -1, int64_t size = -1,
+ std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr) = 0;
RetCode virtual Download(const std::string& name, android::base::borrowed_fd fd, size_t size,
std::string* response = nullptr,
std::vector<std::string>* info = nullptr) = 0;
diff --git a/fastboot/fastboot_driver_mock.h b/fastboot/fastboot_driver_mock.h
index d2a123b..7c41d78 100644
--- a/fastboot/fastboot_driver_mock.h
+++ b/fastboot/fastboot_driver_mock.h
@@ -28,15 +28,16 @@
MOCK_METHOD(RetCode, Reboot, (std::string*, std::vector<std::string>*), (override));
MOCK_METHOD(RetCode, RebootTo, (std::string, std::string*, std::vector<std::string>*),
(override));
-
MOCK_METHOD(RetCode, GetVar, (const std::string&, std::string*, std::vector<std::string>*),
(override));
-
+ MOCK_METHOD(RetCode, FetchToFd,
+ (const std::string&, android::base::borrowed_fd, int64_t offset, int64_t size,
+ std::string*, std::vector<std::string>*),
+ (override));
MOCK_METHOD(RetCode, Download,
(const std::string&, android::base::borrowed_fd, size_t, std::string*,
std::vector<std::string>*),
(override));
-
MOCK_METHOD(RetCode, RawCommand,
(const std::string&, const std::string&, std::string*, std::vector<std::string>*,
int*),
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
index c1b9a31..bf64f0e 100644
--- a/fastboot/task.cpp
+++ b/fastboot/task.cpp
@@ -96,17 +96,17 @@
return "reboot " + reboot_target_;
}
-FlashSuperLayoutTask::FlashSuperLayoutTask(const std::string& super_name,
- std::unique_ptr<SuperFlashHelper> helper,
- SparsePtr sparse_layout, uint64_t super_size,
- const FlashingPlan* fp)
+OptimizedFlashSuperTask::OptimizedFlashSuperTask(const std::string& super_name,
+ std::unique_ptr<SuperFlashHelper> helper,
+ SparsePtr sparse_layout, uint64_t super_size,
+ const FlashingPlan* fp)
: super_name_(super_name),
helper_(std::move(helper)),
sparse_layout_(std::move(sparse_layout)),
super_size_(super_size),
fp_(fp) {}
-void FlashSuperLayoutTask::Run() {
+void OptimizedFlashSuperTask::Run() {
// Use the reported super partition size as the upper limit, rather than
// sparse_file_len, which (1) can fail and (2) is kind of expensive, since
// it will map in all of the embedded fds.
@@ -120,11 +120,11 @@
// Send the data to the device.
flash_partition_files(super_name_, files);
}
-std::string FlashSuperLayoutTask::ToString() {
+std::string OptimizedFlashSuperTask::ToString() {
return "optimized-flash-super";
}
-std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize(
+std::unique_ptr<OptimizedFlashSuperTask> OptimizedFlashSuperTask::Initialize(
const FlashingPlan* fp, std::vector<ImageEntry>& os_images) {
if (!fp->should_optimize_flash_super) {
LOG(INFO) << "super optimization is disabled";
@@ -188,11 +188,11 @@
};
os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback),
os_images.end());
- return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s),
- partition_size, fp);
+ return std::make_unique<OptimizedFlashSuperTask>(super_name, std::move(helper), std::move(s),
+ partition_size, fp);
}
-std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::InitializeFromTasks(
+std::unique_ptr<OptimizedFlashSuperTask> OptimizedFlashSuperTask::InitializeFromTasks(
const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks) {
if (!fp->should_optimize_flash_super) {
LOG(INFO) << "super optimization is disabled";
@@ -261,8 +261,8 @@
};
tasks.erase(std::remove_if(tasks.begin(), tasks.end(), remove_if_callback), tasks.end());
- return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s),
- partition_size, fp);
+ return std::make_unique<OptimizedFlashSuperTask>(super_name, std::move(helper), std::move(s),
+ partition_size, fp);
}
UpdateSuperTask::UpdateSuperTask(const FlashingPlan* fp) : fp_(fp) {}
diff --git a/fastboot/task.h b/fastboot/task.h
index 858f43a..f7c8801 100644
--- a/fastboot/task.h
+++ b/fastboot/task.h
@@ -79,13 +79,13 @@
const FlashingPlan* fp_;
};
-class FlashSuperLayoutTask : public Task {
+class OptimizedFlashSuperTask : public Task {
public:
- FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
- SparsePtr sparse_layout, uint64_t super_size, const FlashingPlan* fp);
- static std::unique_ptr<FlashSuperLayoutTask> Initialize(const FlashingPlan* fp,
- std::vector<ImageEntry>& os_images);
- static std::unique_ptr<FlashSuperLayoutTask> InitializeFromTasks(
+ OptimizedFlashSuperTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
+ SparsePtr sparse_layout, uint64_t super_size, const FlashingPlan* fp);
+ static std::unique_ptr<OptimizedFlashSuperTask> Initialize(const FlashingPlan* fp,
+ std::vector<ImageEntry>& os_images);
+ static std::unique_ptr<OptimizedFlashSuperTask> InitializeFromTasks(
const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks);
using ImageEntry = std::pair<const Image*, std::string>;
void Run() override;
diff --git a/fastboot/task_test.cpp b/fastboot/task_test.cpp
index b4e139b..1ba3f4a 100644
--- a/fastboot/task_test.cpp
+++ b/fastboot/task_test.cpp
@@ -24,6 +24,7 @@
#include <memory>
#include <unordered_map>
#include "android-base/strings.h"
+
using android::base::Split;
using testing::_;
@@ -60,6 +61,33 @@
return ParseFastbootInfoLine(fp, vec_command);
}
+// tests if tasks_a is a superset of tasks_b. Used for checking to ensure all partitions flashed
+// from hardcoded image list is also flashed in new fastboot-info.txt
+static bool compareTaskList(std::vector<std::unique_ptr<Task>>& tasks_a,
+ std::vector<std::unique_ptr<Task>>& tasks_b) {
+ std::set<std::string> list;
+ for (auto& task : tasks_a) {
+ list.insert(task->ToString());
+ }
+ for (auto& task : tasks_b) {
+ if (list.find(task->ToString()) == list.end()) {
+ std::cout << "ERROR: " << task->ToString()
+ << " not found in task list created by fastboot-info.txt";
+ return false;
+ }
+ }
+ return true;
+}
+
+static std::string tasksToString(std::vector<std::unique_ptr<Task>>& tasks) {
+ std::string output;
+ for (auto& task : tasks) {
+ output.append(task->ToString());
+ output.append("\n");
+ }
+ return output;
+}
+
TEST_F(ParseTest, CorrectFlashTaskFormed) {
std::vector<std::string> commands = {"flash dtbo", "flash --slot-other system system_other.img",
"flash system", "flash --apply-vbmeta vbmeta"};
@@ -159,3 +187,51 @@
task->Run();
}
}
+
+TEST_F(ParseTest, CorrectTaskLists) {
+ if (!get_android_product_out()) {
+ GTEST_SKIP();
+ }
+
+ LocalImageSource s;
+ fp->source = &s;
+ fp->sparse_limit = std::numeric_limits<int64_t>::max();
+
+ fastboot::MockFastbootDriver fb;
+ fp->fb = &fb;
+ fp->should_optimize_flash_super = false;
+
+ ON_CALL(fb, GetVar("super-partition-name", _, _))
+ .WillByDefault(testing::Return(fastboot::BAD_ARG));
+
+ FlashAllTool tool(fp.get());
+
+ fp->should_use_fastboot_info = false;
+ auto hardcoded_tasks = tool.CollectTasks();
+ fp->should_use_fastboot_info = true;
+ auto fastboot_info_tasks = tool.CollectTasks();
+
+ auto is_non_flash_task = [](const auto& task) -> bool {
+ return task->AsFlashTask() == nullptr;
+ };
+
+ // remove non flash tasks for testing purposes
+ hardcoded_tasks.erase(
+ std::remove_if(hardcoded_tasks.begin(), hardcoded_tasks.end(), is_non_flash_task),
+ hardcoded_tasks.end());
+ fastboot_info_tasks.erase(std::remove_if(fastboot_info_tasks.begin(), fastboot_info_tasks.end(),
+ is_non_flash_task),
+ fastboot_info_tasks.end());
+
+ if (!compareTaskList(fastboot_info_tasks, hardcoded_tasks)) {
+ std::cout << "\n\n---Hardcoded Task List---\n"
+ << tasksToString(hardcoded_tasks) << "\n---Fastboot-Info Task List---\n"
+ << tasksToString(fastboot_info_tasks);
+ }
+
+ ASSERT_TRUE(compareTaskList(fastboot_info_tasks, hardcoded_tasks));
+
+ ASSERT_TRUE(fastboot_info_tasks.size() >= hardcoded_tasks.size())
+ << "size of fastboot-info task list: " << fastboot_info_tasks.size()
+ << " size of hardcoded task list: " << hardcoded_tasks.size();
+}
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index dd61272..0a836e4 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -49,7 +49,6 @@
sanitize: {
misc_undefined: ["integer"],
},
- local_include_dirs: ["include/"],
cflags: [
"-Wall",
"-Werror",
@@ -60,6 +59,7 @@
name: "libfs_mgr_defaults",
defaults: ["fs_mgr_defaults"],
export_include_dirs: ["include"],
+ local_include_dirs: ["include/"],
include_dirs: ["system/vold"],
cflags: [
"-D_FILE_OFFSET_BITS=64",
@@ -70,8 +70,9 @@
"fs_mgr.cpp",
"fs_mgr_format.cpp",
"fs_mgr_dm_linear.cpp",
- "fs_mgr_overlayfs.cpp",
"fs_mgr_roots.cpp",
+ "fs_mgr_overlayfs_control.cpp",
+ "fs_mgr_overlayfs_mount.cpp",
"fs_mgr_vendor_overlay.cpp",
":libfiemap_srcs",
],
@@ -181,8 +182,13 @@
ramdisk_available: true,
vendor_ramdisk_available: true,
recovery_available: true,
+ apex_available: [
+ "//apex_available:anyapex",
+ "//apex_available:platform",
+ ],
host_supported: true,
defaults: ["fs_mgr_defaults"],
+ local_include_dirs: ["include/"],
srcs: [
"fs_mgr_fstab.cpp",
"fs_mgr_boot_config.cpp",
@@ -206,6 +212,7 @@
"libbase_headers",
"libgsi_headers",
],
+ min_sdk_version: "31",
}
cc_binary {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 7f4959f..e568a9b 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -613,7 +613,6 @@
// Read the primary superblock from an f2fs filesystem. On failure return
// false. If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
-#define F2FS_BLKSIZE 4096
#define F2FS_SUPER_OFFSET 1024
static bool read_f2fs_superblock(const std::string& blk_device, int* fs_stat) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
@@ -628,7 +627,9 @@
PERROR << "Can't read '" << blk_device << "' superblock1";
return false;
}
- if (TEMP_FAILURE_RETRY(pread(fd, &sb2, sizeof(sb2), F2FS_BLKSIZE + F2FS_SUPER_OFFSET)) !=
+ // F2FS only supports block_size=page_size case. So, it is safe to call
+ // `getpagesize()` and use that as size of super block.
+ if (TEMP_FAILURE_RETRY(pread(fd, &sb2, sizeof(sb2), getpagesize() + F2FS_SUPER_OFFSET)) !=
sizeof(sb2)) {
PERROR << "Can't read '" << blk_device << "' superblock2";
return false;
@@ -652,7 +653,7 @@
return false;
}
if (sb == cpu_to_le32(F2FS_SUPER_MAGIC)) return true;
- if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), F2FS_BLKSIZE + F2FS_SUPER_OFFSET)) !=
+ if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), getpagesize() + F2FS_SUPER_OFFSET)) !=
sizeof(sb)) {
return false;
}
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 7385f79..622f181 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -32,6 +32,7 @@
#include <selinux/android.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
+#include <string>
#include "fs_mgr_priv.h"
@@ -68,6 +69,13 @@
/* Format the partition using the calculated length */
+ // EXT4 supports 4K block size on 16K page sizes. A 4K block
+ // size formatted EXT4 partition will mount fine on both 4K and 16K page
+ // size kernels.
+ // However, EXT4 does not support 16K block size on 4K systems.
+ // If we want the same userspace code to work on both 4k/16k kernels,
+ // using a hardcoded 4096 block size is a simple solution. Using
+ // getpagesize() here would work as well, but 4096 is simpler.
std::string size_str = std::to_string(dev_sz / 4096);
std::vector<const char*> mke2fs_args = {"/system/bin/mke2fs", "-t", "ext4", "-b", "4096"};
@@ -127,7 +135,7 @@
/* Format the partition using the calculated length */
- std::string size_str = std::to_string(dev_sz / 4096);
+ const auto size_str = std::to_string(dev_sz / getpagesize());
std::vector<const char*> args = {"/system/bin/make_f2fs", "-g", "android"};
if (needs_projid) {
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index c3c10ba..c85e831 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -51,6 +51,7 @@
namespace {
constexpr char kDefaultAndroidDtDir[] = "/proc/device-tree/firmware/android";
+constexpr char kProcMountsPath[] = "/proc/mounts";
struct FlagList {
const char *name;
@@ -699,9 +700,7 @@
}
}
-bool ReadFstabFromFile(const std::string& path, Fstab* fstab_out) {
- const bool is_proc_mounts = (path == "/proc/mounts");
-
+static bool ReadFstabFromFileCommon(const std::string& path, Fstab* fstab_out) {
std::string fstab_str;
if (!android::base::ReadFileToString(path, &fstab_str, /* follow_symlinks = */ true)) {
PERROR << __FUNCTION__ << "(): failed to read file: '" << path << "'";
@@ -709,11 +708,22 @@
}
Fstab fstab;
- if (!ParseFstabFromString(fstab_str, is_proc_mounts, &fstab)) {
+ if (!ParseFstabFromString(fstab_str, path == kProcMountsPath, &fstab)) {
LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
return false;
}
- if (!is_proc_mounts) {
+
+ EnableMandatoryFlags(&fstab);
+
+ *fstab_out = std::move(fstab);
+ return true;
+}
+
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
+ if (!ReadFstabFromFileCommon(path, fstab)) {
+ return false;
+ }
+ if (path != kProcMountsPath) {
if (!access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
std::string dsu_slot;
if (!android::gsi::GetActiveDsu(&dsu_slot)) {
@@ -725,20 +735,23 @@
PERROR << __FUNCTION__ << "(): failed to read DSU LP names";
return false;
}
- TransformFstabForDsu(&fstab, dsu_slot, Split(lp_names, ","));
+ TransformFstabForDsu(fstab, dsu_slot, Split(lp_names, ","));
} else if (errno != ENOENT) {
PERROR << __FUNCTION__ << "(): failed to access() DSU booted indicator";
return false;
}
+
+ SkipMountingPartitions(fstab, false /* verbose */);
}
-
- SkipMountingPartitions(&fstab, false /* verbose */);
- EnableMandatoryFlags(&fstab);
-
- *fstab_out = std::move(fstab);
return true;
}
+bool ReadFstabFromProcMounts(Fstab* fstab) {
+ // Don't call `ReadFstabFromFile` because the code for `path != kProcMountsPath` has an extra
+ // code size cost, even if it's never executed.
+ return ReadFstabFromFileCommon(kProcMountsPath, fstab);
+}
+
// Returns fstab entries parsed from the device tree if they exist
bool ReadFstabFromDt(Fstab* fstab, bool verbose) {
std::string fstab_buf = ReadFstabFromDt();
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs_control.cpp
similarity index 60%
rename from fs_mgr/fs_mgr_overlayfs.cpp
rename to fs_mgr/fs_mgr_overlayfs_control.cpp
index f04fc8d..69a2ac0 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_control.cpp
@@ -55,8 +55,9 @@
#include <liblp/liblp.h>
#include <storage_literals/storage_literals.h>
+#include "fs_mgr_overlayfs_control.h"
+#include "fs_mgr_overlayfs_mount.h"
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_overlayfs.h"
#include "libfiemap/utility.h"
using namespace std::literals;
@@ -69,100 +70,18 @@
namespace {
constexpr char kDataScratchSizeMbProp[] = "fs_mgr.overlayfs.data_scratch_size_mb";
-constexpr char kPreferCacheBackingStorageProp[] = "fs_mgr.overlayfs.prefer_cache_backing_storage";
-
-bool fs_mgr_access(const std::string& path) {
- return access(path.c_str(), F_OK) == 0;
-}
-
-const auto kLowerdirOption = "lowerdir="s;
-const auto kUpperdirOption = "upperdir="s;
-
-bool fs_mgr_in_recovery() {
- // Check the existence of recovery binary instead of using the compile time
- // __ANDROID_RECOVERY__ macro.
- // If BOARD_USES_RECOVERY_AS_BOOT is true, both normal and recovery boot
- // mode would use the same init binary, which would mean during normal boot
- // the '/init' binary is actually a symlink pointing to
- // init_second_stage.recovery, which would be compiled with
- // __ANDROID_RECOVERY__ defined.
- return fs_mgr_access("/system/bin/recovery");
-}
-
-bool fs_mgr_is_dsu_running() {
- // Since android::gsi::CanBootIntoGsi() or android::gsi::MarkSystemAsGsi() is
- // never called in recovery, the return value of android::gsi::IsGsiRunning()
- // is not well-defined. In this case, just return false as being in recovery
- // implies not running a DSU system.
- if (fs_mgr_in_recovery()) return false;
- return android::gsi::IsGsiRunning();
-}
-
-// list of acceptable overlayfs backing storage
-const auto kScratchMountPoint = "/mnt/scratch"s;
-const auto kCacheMountPoint = "/cache"s;
-
-bool IsABDevice() {
- return !android::base::GetProperty("ro.boot.slot_suffix", "").empty();
-}
-
-std::vector<const std::string> OverlayMountPoints() {
- // Never fallback to legacy cache mount point if within a DSU system,
- // because running a DSU system implies the device supports dynamic
- // partitions, which means legacy cache mustn't be used.
- if (fs_mgr_is_dsu_running()) {
- return {kScratchMountPoint};
- }
-
- // For non-A/B devices prefer cache backing storage if
- // kPreferCacheBackingStorageProp property set.
- if (!IsABDevice() && android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
- android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
- return {kCacheMountPoint, kScratchMountPoint};
- }
-
- return {kScratchMountPoint, kCacheMountPoint};
-}
// Return true if everything is mounted, but before adb is started. Right
// after 'trigger load_persist_props_action' is done.
-bool fs_mgr_boot_completed() {
+static bool fs_mgr_boot_completed() {
return android::base::GetBoolProperty("ro.persistent_properties.ready", false);
}
-bool fs_mgr_is_dir(const std::string& path) {
- struct stat st;
- return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
-}
-
-bool fs_mgr_rw_access(const std::string& path) {
- if (path.empty()) return false;
- return access(path.c_str(), R_OK | W_OK) == 0;
-}
-
-// At less than 1% or 8MB of free space return value of false,
-// means we will try to wrap with overlayfs.
-bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
- // If we have access issues to find out space remaining, return true
- // to prevent us trying to override with overlayfs.
- struct statvfs vst;
- if (statvfs(mount_point.c_str(), &vst)) {
- PLOG(ERROR) << "statvfs " << mount_point;
- return true;
- }
-
- static constexpr int kPercentThreshold = 1; // 1%
- static constexpr unsigned long kSizeThreshold = 8 * 1024 * 1024; // 8MB
-
- return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100)) &&
- (static_cast<uint64_t>(vst.f_bfree) * vst.f_frsize) >= kSizeThreshold;
-}
-
-const auto kPhysicalDevice = "/dev/block/by-name/"s;
+constexpr auto kPhysicalDevice = "/dev/block/by-name/";
constexpr char kScratchImageMetadata[] = "/metadata/gsi/remount/lp_metadata";
// Note: this is meant only for recovery/first-stage init.
-bool ScratchIsOnData() {
+static bool ScratchIsOnData() {
// The scratch partition of DSU is managed by gsid.
if (fs_mgr_is_dsu_running()) {
return false;
@@ -170,97 +89,7 @@
return fs_mgr_access(kScratchImageMetadata);
}
-bool fs_mgr_update_blk_device(FstabEntry* entry) {
- if (entry->fs_mgr_flags.logical) {
- fs_mgr_update_logical_partition(entry);
- }
- if (fs_mgr_access(entry->blk_device)) {
- return true;
- }
- if (entry->blk_device != "/dev/root") {
- return false;
- }
-
- // special case for system-as-root (taimen and others)
- auto blk_device = kPhysicalDevice + "system";
- if (!fs_mgr_access(blk_device)) {
- blk_device += fs_mgr_get_slot_suffix();
- if (!fs_mgr_access(blk_device)) {
- return false;
- }
- }
- entry->blk_device = blk_device;
- return true;
-}
-
-bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
- struct statfs fs;
- if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
- (fs.f_type != EXT4_SUPER_MAGIC)) {
- return false;
- }
-
- android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
- if (fd < 0) return false;
-
- struct ext4_super_block sb;
- if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
- (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
- return false;
- }
-
- struct fs_info info;
- if (ext4_parse_sb(&sb, &info) < 0) return false;
-
- return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
-}
-
-#define F2FS_SUPER_OFFSET 1024
-#define F2FS_FEATURE_OFFSET 2180
-#define F2FS_FEATURE_RO 0x4000
-bool fs_mgr_is_read_only_f2fs(const std::string& dev) {
- if (!fs_mgr_is_f2fs(dev)) return false;
-
- android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
- if (fd < 0) return false;
-
- __le32 feat;
- if ((TEMP_FAILURE_RETRY(lseek64(fd, F2FS_SUPER_OFFSET + F2FS_FEATURE_OFFSET, SEEK_SET)) < 0) ||
- (TEMP_FAILURE_RETRY(read(fd, &feat, sizeof(feat))) < 0)) {
- return false;
- }
-
- return (feat & cpu_to_le32(F2FS_FEATURE_RO)) != 0;
-}
-
-bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
- // readonly filesystem, can not be mount -o remount,rw
- // 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 (!fs_mgr_filesystem_has_space(entry->mount_point)) {
- return true;
- }
-
- // blk_device needs to be setup so we can check superblock.
- // If we fail here, because during init first stage and have doubts.
- if (!fs_mgr_update_blk_device(entry)) {
- return true;
- }
-
- // f2fs read-only mode doesn't support remount,rw
- if (fs_mgr_is_read_only_f2fs(entry->blk_device)) {
- return true;
- }
-
- // check if ext4 de-dupe
- auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
- if (!has_shared_blocks && (entry->mount_point == "/system")) {
- has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device);
- }
- return has_shared_blocks;
-}
-
-bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
+static bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
if (!dir) {
if (errno == ENOENT) {
@@ -301,96 +130,6 @@
return ret;
}
-const auto kUpperName = "upper"s;
-const auto kWorkName = "work"s;
-const auto kOverlayTopDir = "/overlay"s;
-
-std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
- if (!fs_mgr_is_dir(mount_point)) return "";
- const auto base = android::base::Basename(mount_point) + "/";
- for (const auto& overlay_mount_point : OverlayMountPoints()) {
- auto dir = overlay_mount_point + kOverlayTopDir + "/" + base;
- auto upper = dir + kUpperName;
- if (!fs_mgr_is_dir(upper)) continue;
- auto work = dir + kWorkName;
- if (!fs_mgr_is_dir(work)) continue;
- if (!fs_mgr_rw_access(work)) continue;
- return dir;
- }
- return "";
-}
-
-static inline bool KernelSupportsUserXattrs() {
- struct utsname uts;
- uname(&uts);
-
- int major, minor;
- if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
- return false;
- }
- return major > 5 || (major == 5 && minor >= 15);
-}
-
-const std::string fs_mgr_mount_point(const std::string& mount_point) {
- if ("/"s != mount_point) return mount_point;
- return "/system";
-}
-
-// default options for mount_point, returns empty string for none available.
-std::string fs_mgr_get_overlayfs_options(const FstabEntry& entry) {
- const auto mount_point = fs_mgr_mount_point(entry.mount_point);
- auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
- if (candidate.empty()) return "";
- auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
- ",workdir=" + candidate + kWorkName;
- if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
- ret += ",override_creds=off";
- }
- if (KernelSupportsUserXattrs()) {
- ret += ",userxattr";
- }
- for (const auto& flag : android::base::Split(entry.fs_options, ",")) {
- if (android::base::StartsWith(flag, "context=")) {
- ret += "," + flag;
- }
- }
- return ret;
-}
-
-constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
-
-class AutoSetFsCreateCon final {
- public:
- AutoSetFsCreateCon() {}
- AutoSetFsCreateCon(const std::string& context) { Set(context); }
- ~AutoSetFsCreateCon() { Restore(); }
-
- bool Ok() const { return ok_; }
- bool Set(const std::string& context) {
- if (setfscreatecon(context.c_str())) {
- PLOG(ERROR) << "setfscreatecon " << context;
- return false;
- }
- ok_ = true;
- return true;
- }
- bool Restore() {
- if (restored_ || !ok_) {
- return true;
- }
- if (setfscreatecon(nullptr)) {
- PLOG(ERROR) << "setfscreatecon null";
- return false;
- }
- restored_ = true;
- return true;
- }
-
- private:
- bool ok_ = false;
- bool restored_ = false;
-};
-
std::string fs_mgr_overlayfs_setup_dir(const std::string& dir) {
auto top = dir + kOverlayTopDir;
@@ -452,15 +191,15 @@
return true;
}
-uint32_t fs_mgr_overlayfs_slot_number() {
+static uint32_t fs_mgr_overlayfs_slot_number() {
return SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
}
-std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) {
+static std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) {
return kPhysicalDevice + fs_mgr_get_super_partition_name(slot_number);
}
-bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
+static bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
for (const auto& entry : fstab) {
if (entry.fs_mgr_flags.logical) {
return true;
@@ -469,18 +208,6 @@
return false;
}
-// Returns true if immediate unmount succeeded and the scratch mount point was
-// removed.
-bool fs_mgr_overlayfs_umount_scratch() {
- if (umount(kScratchMountPoint.c_str()) != 0) {
- return false;
- }
- if (rmdir(kScratchMountPoint.c_str()) != 0 && errno != ENOENT) {
- PLOG(ERROR) << "rmdir " << kScratchMountPoint;
- }
- return true;
-}
-
OverlayfsTeardownResult TeardownDataScratch(IImageManager* images,
const std::string& partition_name, bool was_mounted) {
if (!images) {
@@ -573,7 +300,7 @@
auto cleanup_all = mount_point.empty();
const auto partition_name = android::base::Basename(mount_point);
const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name));
- const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir.substr(1) + ".teardown"
+ const auto newpath = cleanup_all ? overlay + "/." + (kOverlayTopDir + 1) + ".teardown"
: top + "/." + partition_name + ".teardown";
auto ret = fs_mgr_rm_all(newpath);
if (!rename(oldpath.c_str(), newpath.c_str())) {
@@ -619,214 +346,6 @@
return ret;
}
-bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
- auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
- nullptr);
- if (ret) {
- PERROR << "__mount(target=" << mount_point
- << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
- // If "/system" doesn't look like a mountpoint, retry with "/".
- if (errno == EINVAL && mount_point == "/system") {
- return fs_mgr_overlayfs_set_shared_mount("/", shared_flag);
- }
- return false;
- }
- return true;
-}
-
-bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
- auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
- if (ret) {
- PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
- return false;
- }
- return true;
-}
-
-struct mount_info {
- std::string mount_point;
- bool shared_flag;
-};
-
-std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
- std::vector<mount_info> info;
-
- auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
- if (!file) {
- PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
- return info;
- }
-
- ssize_t len;
- size_t alloc_len = 0;
- char* line = nullptr;
- while ((len = getline(&line, &alloc_len, file.get())) != -1) {
- /* if the last character is a newline, shorten the string by 1 byte */
- if (line[len - 1] == '\n') {
- line[len - 1] = '\0';
- }
-
- static constexpr char delim[] = " \t";
- char* save_ptr;
- if (!strtok_r(line, delim, &save_ptr)) {
- LERROR << "Error parsing mount ID";
- break;
- }
- if (!strtok_r(nullptr, delim, &save_ptr)) {
- LERROR << "Error parsing parent ID";
- break;
- }
- if (!strtok_r(nullptr, delim, &save_ptr)) {
- LERROR << "Error parsing mount source";
- break;
- }
- if (!strtok_r(nullptr, delim, &save_ptr)) {
- LERROR << "Error parsing root";
- break;
- }
-
- char* p;
- if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
- LERROR << "Error parsing mount_point";
- break;
- }
- mount_info entry = {p, false};
-
- if (!strtok_r(nullptr, delim, &save_ptr)) {
- LERROR << "Error parsing mount_flags";
- break;
- }
-
- while ((p = strtok_r(nullptr, delim, &save_ptr))) {
- if ((p[0] == '-') && (p[1] == '\0')) break;
- if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
- }
- if (!p) {
- LERROR << "Error parsing fields";
- break;
- }
- info.emplace_back(std::move(entry));
- }
-
- free(line);
- if (info.empty()) {
- LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
- }
- return info;
-}
-
-bool fs_mgr_overlayfs_mount(const FstabEntry& entry) {
- const auto mount_point = fs_mgr_mount_point(entry.mount_point);
- const auto options = fs_mgr_get_overlayfs_options(entry);
- if (options.empty()) return false;
-
- auto retval = true;
-
- struct move_entry {
- std::string mount_point;
- std::string dir;
- bool shared_flag;
- };
- std::vector<move_entry> move;
- auto parent_private = false;
- auto parent_made_private = false;
- auto dev_private = false;
- auto dev_made_private = false;
- for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
- if ((entry.mount_point == mount_point) && !entry.shared_flag) {
- parent_private = true;
- }
- if ((entry.mount_point == "/dev") && !entry.shared_flag) {
- dev_private = true;
- }
-
- if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
- continue;
- }
- if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
- return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
- }) != move.end()) {
- continue;
- }
-
- // use as the bound directory in /dev.
- AutoSetFsCreateCon createcon;
- auto new_context = fs_mgr_get_context(entry.mount_point);
- if (new_context.empty() || !createcon.Set(new_context)) {
- continue;
- }
- move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
- entry.shared_flag};
- const auto target = mkdtemp(new_entry.dir.data());
- if (!createcon.Restore()) {
- return false;
- }
- if (!target) {
- retval = false;
- PERROR << "temporary directory for MS_BIND";
- continue;
- }
-
- if (!parent_private && !parent_made_private) {
- parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
- }
- if (new_entry.shared_flag) {
- new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
- }
- if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
- retval = false;
- if (new_entry.shared_flag) {
- fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
- }
- continue;
- }
- move.emplace_back(std::move(new_entry));
- }
-
- // hijack __mount() report format to help triage
- auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
- const auto opt_list = android::base::Split(options, ",");
- for (const auto& opt : opt_list) {
- if (android::base::StartsWith(opt, kUpperdirOption)) {
- report = report + "," + opt;
- break;
- }
- }
- report = report + ")=";
-
- auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
- options.c_str());
- if (ret) {
- retval = false;
- PERROR << report << ret;
- } else {
- LINFO << report << ret;
- }
-
- // Move submounts back.
- for (const auto& entry : move) {
- if (!dev_private && !dev_made_private) {
- dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
- }
-
- if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
- retval = false;
- } else if (entry.shared_flag &&
- !fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
- retval = false;
- }
- rmdir(entry.dir.c_str());
- }
- if (dev_made_private) {
- fs_mgr_overlayfs_set_shared_mount("/dev", true);
- }
- if (parent_made_private) {
- fs_mgr_overlayfs_set_shared_mount(mount_point, true);
- }
-
- return retval;
-}
-
// Mount kScratchMountPoint
bool MountScratch(const std::string& device_path, bool readonly = false) {
if (readonly) {
@@ -853,7 +372,7 @@
if (!createcon.Ok()) {
return false;
}
- if (mkdir(kScratchMountPoint.c_str(), 0755) && (errno != EEXIST)) {
+ if (mkdir(kScratchMountPoint, 0755) && (errno != EEXIST)) {
PERROR << "create " << kScratchMountPoint;
return false;
}
@@ -884,7 +403,7 @@
return false;
}
if (!mounted) {
- rmdir(kScratchMountPoint.c_str());
+ rmdir(kScratchMountPoint);
return false;
}
return true;
@@ -939,7 +458,9 @@
auto command = ""s;
if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) {
fs_type = "f2fs";
- command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
+ command = kMkF2fs + " -w ";
+ command += std::to_string(getpagesize());
+ command += " -f -d1 -l" + android::base::Basename(kScratchMountPoint);
} else if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) {
fs_type = "ext4";
command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
@@ -1008,21 +529,7 @@
auto partition_size =
builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
if ((partition_size > kMinimumSize) || !partition->size()) {
- // Leave some space for free space jitter of a few erase
- // blocks, in case they are needed for any individual updates
- // to any other partition that needs to be flashed while
- // overlayfs is in force. Of course if margin_size is not
- // enough could normally get a flash failure, so
- // ResizePartition() will delete the scratch partition in
- // order to fulfill. Deleting scratch will destroy all of
- // the adb remount overrides :-( .
- auto margin_size = uint64_t(3 * 256 * 1024);
- BlockDeviceInfo info;
- if (builder->GetBlockDeviceInfo(fs_mgr_get_super_partition_name(slot_number), &info)) {
- margin_size = 3 * info.logical_block_size;
- }
- partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
- partition_size / 2);
+ partition_size = std::max(std::min(kMinimumSize, partition_size), partition_size / 2);
if (partition_size > partition->size()) {
if (!builder->ResizePartition(partition, partition_size)) {
// Try to free up space by deallocating partitions in the other slot.
@@ -1030,8 +537,8 @@
partition_size =
builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
- partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
- partition_size / 2);
+ partition_size =
+ std::max(std::min(kMinimumSize, partition_size), partition_size / 2);
if (!builder->ResizePartition(partition, partition_size)) {
LERROR << "resize " << partition_name;
return false;
@@ -1190,7 +697,7 @@
// If the partition exists, assume first that it can be mounted.
if (partition_exists) {
if (MountScratch(scratch_device)) {
- if (fs_mgr_access(kScratchMountPoint + kOverlayTopDir) ||
+ if (fs_mgr_access(std::string(kScratchMountPoint) + kOverlayTopDir) ||
fs_mgr_filesystem_has_space(kScratchMountPoint)) {
return true;
}
@@ -1210,12 +717,6 @@
return MountScratch(scratch_device);
}
-#if ALLOW_ADBD_DISABLE_VERITY
-constexpr bool kAllowOverlayfs = true;
-#else
-constexpr bool kAllowOverlayfs = false;
-#endif
-
// NOTE: OverlayfsSetupAllowed() must be "stricter" than OverlayfsTeardownAllowed().
// Setup is allowed only if teardown is also allowed.
bool OverlayfsSetupAllowed(bool verbose = false) {
@@ -1249,114 +750,6 @@
} // namespace
-bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
- // Don't check entries that are managed by vold.
- if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
-
- // *_other doesn't want overlayfs.
- if (entry->fs_mgr_flags.slot_select_other) return false;
-
- // Only concerned with readonly partitions.
- if (!(entry->flags & MS_RDONLY)) return false;
-
- // If unbindable, do not allow overlayfs as this could expose us to
- // security issues. On Android, this could also be used to turn off
- // the ability to overlay an otherwise acceptable filesystem since
- // /system and /vendor are never bound(sic) to.
- if (entry->flags & MS_UNBINDABLE) return false;
-
- if (!fs_mgr_overlayfs_enabled(entry)) return false;
-
- return true;
-}
-
-Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
- android::fs_mgr::Fstab mounts;
- if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
- PLOG(ERROR) << "Failed to read /proc/mounts";
- return {};
- }
-
- Fstab candidates;
- for (const auto& entry : fstab) {
- // Filter out partitions whose type doesn't match what's mounted.
- // This avoids spammy behavior on devices which can mount different
- // filesystems for each partition.
- auto proc_mount_point = (entry.mount_point == "/system") ? "/" : entry.mount_point;
- auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
- if (!mounted || mounted->fs_type != entry.fs_type) {
- continue;
- }
-
- FstabEntry new_entry = entry;
- if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
- !fs_mgr_wants_overlayfs(&new_entry)) {
- continue;
- }
- auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
- auto duplicate_or_more_specific = false;
- for (auto it = candidates.begin(); it != candidates.end();) {
- auto it_mount_point = fs_mgr_mount_point(it->mount_point);
- if ((it_mount_point == new_mount_point) ||
- (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
- duplicate_or_more_specific = true;
- break;
- }
- if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
- it = candidates.erase(it);
- } else {
- ++it;
- }
- }
- if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
- }
- return candidates;
-}
-
-static void TryMountScratch() {
- // Note we get the boot scratch device here, which means if scratch was
- // just created through ImageManager, this could fail. In practice this
- // should not happen because "remount" detects this scenario (by checking
- // if verity is still disabled, i.e. no reboot occurred), and skips calling
- // fs_mgr_overlayfs_mount_all().
- auto scratch_device = GetBootScratchDevice();
- if (!fs_mgr_rw_access(scratch_device)) {
- return;
- }
- if (!WaitForFile(scratch_device, 10s)) {
- return;
- }
- if (!MountScratch(scratch_device, true /* readonly */)) {
- return;
- }
- auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
- fs_mgr_overlayfs_umount_scratch();
- if (has_overlayfs_dir) {
- MountScratch(scratch_device);
- }
-}
-
-bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
- if (!OverlayfsSetupAllowed()) {
- return false;
- }
- auto ret = true;
- auto scratch_can_be_mounted = true;
- for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
- if (fs_mgr_is_verity_enabled(entry)) continue;
- auto mount_point = fs_mgr_mount_point(entry.mount_point);
- if (fs_mgr_overlayfs_already_mounted(mount_point)) {
- continue;
- }
- if (scratch_can_be_mounted) {
- scratch_can_be_mounted = false;
- TryMountScratch();
- }
- ret &= fs_mgr_overlayfs_mount(entry);
- }
- return ret;
-}
-
bool fs_mgr_overlayfs_setup(const Fstab& fstab, const char* mount_point, bool* want_reboot,
bool just_disabled_verity) {
if (!OverlayfsSetupAllowed(/*verbose=*/true)) {
@@ -1580,22 +973,6 @@
return rv;
}
-bool fs_mgr_overlayfs_is_setup() {
- if (!OverlayfsSetupAllowed()) {
- return false;
- }
- if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
- Fstab fstab;
- if (!ReadDefaultFstab(&fstab)) {
- return false;
- }
- for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
- if (fs_mgr_is_verity_enabled(entry)) continue;
- if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
- }
- return false;
-}
-
namespace android {
namespace fs_mgr {
@@ -1712,23 +1089,3 @@
} // namespace fs_mgr
} // namespace android
-
-bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
- Fstab fstab;
- if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
- return false;
- }
- const auto lowerdir = kLowerdirOption + mount_point;
- for (const auto& entry : fstab) {
- if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
- if (mount_point != entry.mount_point) continue;
- if (!overlay_only) return true;
- const auto options = android::base::Split(entry.fs_options, ",");
- for (const auto& opt : options) {
- if (opt == lowerdir) {
- return true;
- }
- }
- }
- return false;
-}
diff --git a/fs_mgr/fs_mgr_overlayfs_control.h b/fs_mgr/fs_mgr_overlayfs_control.h
new file mode 100644
index 0000000..50e83e8
--- /dev/null
+++ b/fs_mgr/fs_mgr_overlayfs_control.h
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 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 <string>
+
+#include <fstab/fstab.h>
+
+// If "mount_point" is non-null, set up exactly one overlay.
+//
+// If "mount_point" is null, setup any overlays.
+//
+// If |want_reboot| is non-null, and a reboot is needed to apply overlays, then
+// it will be true on return. The caller is responsible for initializing it.
+bool fs_mgr_overlayfs_setup(const android::fs_mgr::Fstab& fstab, const char* mount_point = nullptr,
+ bool* want_reboot = nullptr, bool just_disabled_verity = true);
+
+enum class OverlayfsTeardownResult {
+ Ok,
+ Busy, // Indicates that overlays are still in use.
+ Error
+};
+OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
+ bool* want_reboot = nullptr);
+
+namespace android {
+namespace fs_mgr {
+
+void CleanupOldScratchFiles();
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
new file mode 100644
index 0000000..c057c2b
--- /dev/null
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -0,0 +1,802 @@
+/*
+ * 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.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <selinux/selinux.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr.h>
+#include <fs_mgr/file_wait.h>
+#include <fs_mgr_dm_linear.h>
+#include <fs_mgr_overlayfs.h>
+#include <fstab/fstab.h>
+#include <libdm/dm.h>
+#include <libgsi/libgsi.h>
+#include <storage_literals/storage_literals.h>
+
+#include "fs_mgr_overlayfs_mount.h"
+#include "fs_mgr_priv.h"
+
+using namespace std::literals;
+using namespace android::dm;
+using namespace android::fs_mgr;
+using namespace android::storage_literals;
+
+constexpr char kPreferCacheBackingStorageProp[] = "fs_mgr.overlayfs.prefer_cache_backing_storage";
+
+bool fs_mgr_access(const std::string& path) {
+ return access(path.c_str(), F_OK) == 0;
+}
+
+const auto kLowerdirOption = "lowerdir=";
+const auto kUpperdirOption = "upperdir=";
+
+bool fs_mgr_in_recovery() {
+ // Check the existence of recovery binary instead of using the compile time
+ // __ANDROID_RECOVERY__ macro.
+ // If BOARD_USES_RECOVERY_AS_BOOT is true, both normal and recovery boot
+ // mode would use the same init binary, which would mean during normal boot
+ // the '/init' binary is actually a symlink pointing to
+ // init_second_stage.recovery, which would be compiled with
+ // __ANDROID_RECOVERY__ defined.
+ return fs_mgr_access("/system/bin/recovery");
+}
+
+bool fs_mgr_is_dsu_running() {
+ // Since android::gsi::CanBootIntoGsi() or android::gsi::MarkSystemAsGsi() is
+ // never called in recovery, the return value of android::gsi::IsGsiRunning()
+ // is not well-defined. In this case, just return false as being in recovery
+ // implies not running a DSU system.
+ if (fs_mgr_in_recovery()) return false;
+ return android::gsi::IsGsiRunning();
+}
+
+const auto kCacheMountPoint = "/cache";
+
+static bool IsABDevice() {
+ return !android::base::GetProperty("ro.boot.slot_suffix", "").empty();
+}
+
+std::vector<const std::string> OverlayMountPoints() {
+ // Never fallback to legacy cache mount point if within a DSU system,
+ // because running a DSU system implies the device supports dynamic
+ // partitions, which means legacy cache mustn't be used.
+ if (fs_mgr_is_dsu_running()) {
+ return {kScratchMountPoint};
+ }
+
+ // For non-A/B devices prefer cache backing storage if
+ // kPreferCacheBackingStorageProp property set.
+ if (!IsABDevice() && android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
+ android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
+ return {kCacheMountPoint, kScratchMountPoint};
+ }
+
+ return {kScratchMountPoint, kCacheMountPoint};
+}
+
+static bool fs_mgr_is_dir(const std::string& path) {
+ struct stat st;
+ return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
+}
+
+bool fs_mgr_rw_access(const std::string& path) {
+ if (path.empty()) return false;
+ return access(path.c_str(), R_OK | W_OK) == 0;
+}
+
+// At less than 1% or 8MB of free space return value of false,
+// means we will try to wrap with overlayfs.
+bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
+ // If we have access issues to find out space remaining, return true
+ // to prevent us trying to override with overlayfs.
+ struct statvfs vst;
+ if (statvfs(mount_point.c_str(), &vst)) {
+ PLOG(ERROR) << "statvfs " << mount_point;
+ return true;
+ }
+
+ static constexpr int kPercentThreshold = 1; // 1%
+ static constexpr unsigned long kSizeThreshold = 8 * 1024 * 1024; // 8MB
+
+ return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100)) &&
+ (static_cast<uint64_t>(vst.f_bfree) * vst.f_frsize) >= kSizeThreshold;
+}
+
+const auto kPhysicalDevice = "/dev/block/by-name/";
+
+static bool fs_mgr_update_blk_device(FstabEntry* entry) {
+ if (entry->fs_mgr_flags.logical) {
+ fs_mgr_update_logical_partition(entry);
+ }
+ if (fs_mgr_access(entry->blk_device)) {
+ return true;
+ }
+ if (entry->blk_device != "/dev/root") {
+ return false;
+ }
+
+ // special case for system-as-root (taimen and others)
+ auto blk_device = std::string(kPhysicalDevice) + "system";
+ if (!fs_mgr_access(blk_device)) {
+ blk_device += fs_mgr_get_slot_suffix();
+ if (!fs_mgr_access(blk_device)) {
+ return false;
+ }
+ }
+ entry->blk_device = blk_device;
+ return true;
+}
+
+static bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
+ struct statfs fs;
+ if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
+ (fs.f_type != EXT4_SUPER_MAGIC)) {
+ return false;
+ }
+
+ android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) return false;
+
+ struct ext4_super_block sb;
+ if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
+ (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
+ return false;
+ }
+
+ struct fs_info info;
+ if (ext4_parse_sb(&sb, &info) < 0) return false;
+
+ return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
+}
+
+#define F2FS_SUPER_OFFSET 1024
+#define F2FS_FEATURE_OFFSET 2180
+#define F2FS_FEATURE_RO 0x4000
+static bool fs_mgr_is_read_only_f2fs(const std::string& dev) {
+ if (!fs_mgr_is_f2fs(dev)) return false;
+
+ android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) return false;
+
+ __le32 feat;
+ if ((TEMP_FAILURE_RETRY(lseek64(fd, F2FS_SUPER_OFFSET + F2FS_FEATURE_OFFSET, SEEK_SET)) < 0) ||
+ (TEMP_FAILURE_RETRY(read(fd, &feat, sizeof(feat))) < 0)) {
+ return false;
+ }
+
+ return (feat & cpu_to_le32(F2FS_FEATURE_RO)) != 0;
+}
+
+static bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
+ // readonly filesystem, can not be mount -o remount,rw
+ // 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 (!fs_mgr_filesystem_has_space(entry->mount_point)) {
+ return true;
+ }
+
+ // blk_device needs to be setup so we can check superblock.
+ // If we fail here, because during init first stage and have doubts.
+ if (!fs_mgr_update_blk_device(entry)) {
+ return true;
+ }
+
+ // f2fs read-only mode doesn't support remount,rw
+ if (fs_mgr_is_read_only_f2fs(entry->blk_device)) {
+ return true;
+ }
+
+ // check if ext4 de-dupe
+ auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
+ if (!has_shared_blocks && (entry->mount_point == "/system")) {
+ has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device);
+ }
+ return has_shared_blocks;
+}
+
+static std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
+ if (!fs_mgr_is_dir(mount_point)) return "";
+ const auto base = android::base::Basename(mount_point) + "/";
+ for (const auto& overlay_mount_point : OverlayMountPoints()) {
+ auto dir = overlay_mount_point + kOverlayTopDir + "/" + base;
+ auto upper = dir + kUpperName;
+ if (!fs_mgr_is_dir(upper)) continue;
+ auto work = dir + kWorkName;
+ if (!fs_mgr_is_dir(work)) continue;
+ if (!fs_mgr_rw_access(work)) continue;
+ return dir;
+ }
+ return "";
+}
+
+static inline bool KernelSupportsUserXattrs() {
+ struct utsname uts;
+ uname(&uts);
+
+ int major, minor;
+ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+ return false;
+ }
+ return major > 5 || (major == 5 && minor >= 15);
+}
+
+const std::string fs_mgr_mount_point(const std::string& mount_point) {
+ if ("/"s != mount_point) return mount_point;
+ return "/system";
+}
+
+// default options for mount_point, returns empty string for none available.
+static std::string fs_mgr_get_overlayfs_options(const FstabEntry& entry) {
+ const auto mount_point = fs_mgr_mount_point(entry.mount_point);
+ auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
+ if (candidate.empty()) return "";
+ auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
+ ",workdir=" + candidate + kWorkName;
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
+ ret += ",override_creds=off";
+ }
+ if (KernelSupportsUserXattrs()) {
+ ret += ",userxattr";
+ }
+ for (const auto& flag : android::base::Split(entry.fs_options, ",")) {
+ if (android::base::StartsWith(flag, "context=")) {
+ ret += "," + flag;
+ }
+ }
+ return ret;
+}
+
+bool AutoSetFsCreateCon::Set(const std::string& context) {
+ if (setfscreatecon(context.c_str())) {
+ PLOG(ERROR) << "setfscreatecon " << context;
+ return false;
+ }
+ ok_ = true;
+ return true;
+}
+
+bool AutoSetFsCreateCon::Restore() {
+ if (restored_ || !ok_) {
+ return true;
+ }
+ if (setfscreatecon(nullptr)) {
+ PLOG(ERROR) << "setfscreatecon null";
+ return false;
+ }
+ restored_ = true;
+ return true;
+}
+
+// Returns true if immediate unmount succeeded and the scratch mount point was
+// removed.
+bool fs_mgr_overlayfs_umount_scratch() {
+ if (umount(kScratchMountPoint) != 0) {
+ return false;
+ }
+ if (rmdir(kScratchMountPoint) != 0 && errno != ENOENT) {
+ PLOG(ERROR) << "rmdir " << kScratchMountPoint;
+ }
+ return true;
+}
+
+static bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
+ auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
+ nullptr);
+ if (ret) {
+ PERROR << "__mount(target=" << mount_point
+ << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
+ // If "/system" doesn't look like a mountpoint, retry with "/".
+ if (errno == EINVAL && mount_point == "/system") {
+ return fs_mgr_overlayfs_set_shared_mount("/", shared_flag);
+ }
+ return false;
+ }
+ return true;
+}
+
+static bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
+ auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
+ if (ret) {
+ PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
+ return false;
+ }
+ return true;
+}
+
+struct mount_info {
+ std::string mount_point;
+ bool shared_flag;
+};
+
+static std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
+ std::vector<mount_info> info;
+
+ auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
+ if (!file) {
+ PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
+ return info;
+ }
+
+ ssize_t len;
+ size_t alloc_len = 0;
+ char* line = nullptr;
+ while ((len = getline(&line, &alloc_len, file.get())) != -1) {
+ /* if the last character is a newline, shorten the string by 1 byte */
+ if (line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ }
+
+ static constexpr char delim[] = " \t";
+ char* save_ptr;
+ if (!strtok_r(line, delim, &save_ptr)) {
+ LERROR << "Error parsing mount ID";
+ break;
+ }
+ if (!strtok_r(nullptr, delim, &save_ptr)) {
+ LERROR << "Error parsing parent ID";
+ break;
+ }
+ if (!strtok_r(nullptr, delim, &save_ptr)) {
+ LERROR << "Error parsing mount source";
+ break;
+ }
+ if (!strtok_r(nullptr, delim, &save_ptr)) {
+ LERROR << "Error parsing root";
+ break;
+ }
+
+ char* p;
+ if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
+ LERROR << "Error parsing mount_point";
+ break;
+ }
+ mount_info entry = {p, false};
+
+ if (!strtok_r(nullptr, delim, &save_ptr)) {
+ LERROR << "Error parsing mount_flags";
+ break;
+ }
+
+ while ((p = strtok_r(nullptr, delim, &save_ptr))) {
+ if ((p[0] == '-') && (p[1] == '\0')) break;
+ if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
+ }
+ if (!p) {
+ LERROR << "Error parsing fields";
+ break;
+ }
+ info.emplace_back(std::move(entry));
+ }
+
+ free(line);
+ if (info.empty()) {
+ LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
+ }
+ return info;
+}
+
+static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) {
+ const auto mount_point = fs_mgr_mount_point(entry.mount_point);
+ const auto options = fs_mgr_get_overlayfs_options(entry);
+ if (options.empty()) return false;
+
+ auto retval = true;
+
+ struct move_entry {
+ std::string mount_point;
+ std::string dir;
+ bool shared_flag;
+ };
+ std::vector<move_entry> move;
+ auto parent_private = false;
+ auto parent_made_private = false;
+ auto dev_private = false;
+ auto dev_made_private = false;
+ for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
+ if ((entry.mount_point == mount_point) && !entry.shared_flag) {
+ parent_private = true;
+ }
+ if ((entry.mount_point == "/dev") && !entry.shared_flag) {
+ dev_private = true;
+ }
+
+ if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
+ continue;
+ }
+ if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
+ return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
+ }) != move.end()) {
+ continue;
+ }
+
+ // use as the bound directory in /dev.
+ AutoSetFsCreateCon createcon;
+ auto new_context = fs_mgr_get_context(entry.mount_point);
+ if (new_context.empty() || !createcon.Set(new_context)) {
+ continue;
+ }
+ move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
+ entry.shared_flag};
+ const auto target = mkdtemp(new_entry.dir.data());
+ if (!createcon.Restore()) {
+ return false;
+ }
+ if (!target) {
+ retval = false;
+ PERROR << "temporary directory for MS_BIND";
+ continue;
+ }
+
+ if (!parent_private && !parent_made_private) {
+ parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+ }
+ if (new_entry.shared_flag) {
+ new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
+ }
+ if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
+ retval = false;
+ if (new_entry.shared_flag) {
+ fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
+ }
+ continue;
+ }
+ move.emplace_back(std::move(new_entry));
+ }
+
+ // hijack __mount() report format to help triage
+ auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
+ const auto opt_list = android::base::Split(options, ",");
+ for (const auto& opt : opt_list) {
+ if (android::base::StartsWith(opt, kUpperdirOption)) {
+ report = report + "," + opt;
+ break;
+ }
+ }
+ report = report + ")=";
+
+ auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
+ options.c_str());
+ if (ret) {
+ retval = false;
+ PERROR << report << ret;
+ } else {
+ LINFO << report << ret;
+ }
+
+ // Move submounts back.
+ for (const auto& entry : move) {
+ if (!dev_private && !dev_made_private) {
+ dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
+ }
+
+ if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
+ retval = false;
+ } else if (entry.shared_flag &&
+ !fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
+ retval = false;
+ }
+ rmdir(entry.dir.c_str());
+ }
+ if (dev_made_private) {
+ fs_mgr_overlayfs_set_shared_mount("/dev", true);
+ }
+ if (parent_made_private) {
+ fs_mgr_overlayfs_set_shared_mount(mount_point, true);
+ }
+
+ return retval;
+}
+
+// Mount kScratchMountPoint
+static bool MountScratch(const std::string& device_path, bool readonly = false) {
+ if (readonly) {
+ if (!fs_mgr_access(device_path)) {
+ LOG(ERROR) << "Path does not exist: " << device_path;
+ return false;
+ }
+ } else if (!fs_mgr_rw_access(device_path)) {
+ LOG(ERROR) << "Path does not exist or is not readwrite: " << device_path;
+ return false;
+ }
+
+ std::vector<const char*> filesystem_candidates;
+ if (fs_mgr_is_f2fs(device_path)) {
+ filesystem_candidates = {"f2fs", "ext4"};
+ } else if (fs_mgr_is_ext4(device_path)) {
+ filesystem_candidates = {"ext4", "f2fs"};
+ } else {
+ LOG(ERROR) << "Scratch partition is not f2fs or ext4";
+ return false;
+ }
+
+ AutoSetFsCreateCon createcon(kOverlayfsFileContext);
+ if (!createcon.Ok()) {
+ return false;
+ }
+ if (mkdir(kScratchMountPoint, 0755) && (errno != EEXIST)) {
+ PERROR << "create " << kScratchMountPoint;
+ return false;
+ }
+
+ FstabEntry entry;
+ entry.blk_device = device_path;
+ entry.mount_point = kScratchMountPoint;
+ entry.flags = MS_NOATIME | MS_RDONLY;
+ if (!readonly) {
+ entry.flags &= ~MS_RDONLY;
+ entry.flags |= MS_SYNCHRONOUS;
+ entry.fs_options = "nodiscard";
+ fs_mgr_set_blk_ro(device_path, false);
+ }
+ // check_fs requires apex runtime library
+ if (fs_mgr_overlayfs_already_mounted("/data", false)) {
+ entry.fs_mgr_flags.check = true;
+ }
+ bool mounted = false;
+ for (auto fs_type : filesystem_candidates) {
+ entry.fs_type = fs_type;
+ if (fs_mgr_do_mount_one(entry) == 0) {
+ mounted = true;
+ break;
+ }
+ }
+ if (!createcon.Restore()) {
+ return false;
+ }
+ if (!mounted) {
+ rmdir(kScratchMountPoint);
+ return false;
+ }
+ return true;
+}
+
+const std::string kMkF2fs("/system/bin/make_f2fs");
+const std::string kMkExt4("/system/bin/mke2fs");
+
+// Note: The scratch partition of DSU is managed by gsid, and should be initialized during
+// first-stage-mount. Just check if the DM device for DSU scratch partition is created or not.
+static std::string GetDsuScratchDevice() {
+ auto& dm = DeviceMapper::Instance();
+ std::string device;
+ if (dm.GetState(android::gsi::kDsuScratch) != DmDeviceState::INVALID &&
+ dm.GetDmDevicePathByName(android::gsi::kDsuScratch, &device)) {
+ return device;
+ }
+ return "";
+}
+
+// This returns the scratch device that was detected during early boot (first-
+// stage init). If the device was created later, for example during setup for
+// the adb remount command, it can return an empty string since it does not
+// query ImageManager. (Note that ImageManager in first-stage init will always
+// use device-mapper, since /data is not available to use loop devices.)
+static std::string GetBootScratchDevice() {
+ // Note: fs_mgr_is_dsu_running() always returns false in recovery or fastbootd.
+ if (fs_mgr_is_dsu_running()) {
+ return GetDsuScratchDevice();
+ }
+
+ auto& dm = DeviceMapper::Instance();
+
+ // If there is a scratch partition allocated in /data or on super, we
+ // automatically prioritize that over super_other or system_other.
+ // Some devices, for example, have a write-protected eMMC and the
+ // super partition cannot be used even if it exists.
+ std::string device;
+ auto partition_name = android::base::Basename(kScratchMountPoint);
+ if (dm.GetState(partition_name) != DmDeviceState::INVALID &&
+ dm.GetDmDevicePathByName(partition_name, &device)) {
+ return device;
+ }
+
+ return "";
+}
+
+// NOTE: OverlayfsSetupAllowed() must be "stricter" than OverlayfsTeardownAllowed().
+// Setup is allowed only if teardown is also allowed.
+bool OverlayfsSetupAllowed(bool verbose = false) {
+ if (!kAllowOverlayfs) {
+ if (verbose) {
+ LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
+ }
+ return false;
+ }
+ // Check mandatory kernel patches.
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
+ if (verbose) {
+ LOG(ERROR) << "Kernel does not support overlayfs";
+ }
+ return false;
+ }
+ // in recovery or fastbootd, not allowed!
+ if (fs_mgr_in_recovery()) {
+ if (verbose) {
+ LOG(ERROR) << "Unsupported overlayfs setup from recovery";
+ }
+ return false;
+ }
+ return true;
+}
+
+bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
+ // Don't check entries that are managed by vold.
+ if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
+
+ // *_other doesn't want overlayfs.
+ if (entry->fs_mgr_flags.slot_select_other) return false;
+
+ // Only concerned with readonly partitions.
+ if (!(entry->flags & MS_RDONLY)) return false;
+
+ // If unbindable, do not allow overlayfs as this could expose us to
+ // security issues. On Android, this could also be used to turn off
+ // the ability to overlay an otherwise acceptable filesystem since
+ // /system and /vendor are never bound(sic) to.
+ if (entry->flags & MS_UNBINDABLE) return false;
+
+ if (!fs_mgr_overlayfs_enabled(entry)) return false;
+
+ return true;
+}
+
+Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
+ android::fs_mgr::Fstab mounts;
+ if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
+ PLOG(ERROR) << "Failed to read /proc/mounts";
+ return {};
+ }
+
+ Fstab candidates;
+ for (const auto& entry : fstab) {
+ // Filter out partitions whose type doesn't match what's mounted.
+ // This avoids spammy behavior on devices which can mount different
+ // filesystems for each partition.
+ auto proc_mount_point = (entry.mount_point == "/system") ? "/" : entry.mount_point;
+ auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
+ if (!mounted || mounted->fs_type != entry.fs_type) {
+ continue;
+ }
+
+ FstabEntry new_entry = entry;
+ if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
+ !fs_mgr_wants_overlayfs(&new_entry)) {
+ continue;
+ }
+ auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
+ auto duplicate_or_more_specific = false;
+ for (auto it = candidates.begin(); it != candidates.end();) {
+ auto it_mount_point = fs_mgr_mount_point(it->mount_point);
+ if ((it_mount_point == new_mount_point) ||
+ (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
+ duplicate_or_more_specific = true;
+ break;
+ }
+ if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
+ it = candidates.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
+ }
+ return candidates;
+}
+
+static void TryMountScratch() {
+ // Note we get the boot scratch device here, which means if scratch was
+ // just created through ImageManager, this could fail. In practice this
+ // should not happen because "remount" detects this scenario (by checking
+ // if verity is still disabled, i.e. no reboot occurred), and skips calling
+ // fs_mgr_overlayfs_mount_all().
+ auto scratch_device = GetBootScratchDevice();
+ if (!fs_mgr_rw_access(scratch_device)) {
+ return;
+ }
+ if (!WaitForFile(scratch_device, 10s)) {
+ return;
+ }
+ if (!MountScratch(scratch_device, true /* readonly */)) {
+ return;
+ }
+ auto has_overlayfs_dir = fs_mgr_access(std::string(kScratchMountPoint) + kOverlayTopDir);
+ fs_mgr_overlayfs_umount_scratch();
+ if (has_overlayfs_dir) {
+ MountScratch(scratch_device);
+ }
+}
+
+bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
+ if (!OverlayfsSetupAllowed()) {
+ return false;
+ }
+ auto ret = true;
+ auto scratch_can_be_mounted = true;
+ for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
+ if (fs_mgr_is_verity_enabled(entry)) continue;
+ auto mount_point = fs_mgr_mount_point(entry.mount_point);
+ if (fs_mgr_overlayfs_already_mounted(mount_point)) {
+ continue;
+ }
+ if (scratch_can_be_mounted) {
+ scratch_can_be_mounted = false;
+ TryMountScratch();
+ }
+ ret &= fs_mgr_overlayfs_mount(entry);
+ }
+ return ret;
+}
+
+bool fs_mgr_overlayfs_is_setup() {
+ if (!OverlayfsSetupAllowed()) {
+ return false;
+ }
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return false;
+ }
+ for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
+ if (fs_mgr_is_verity_enabled(entry)) continue;
+ if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
+ }
+ return false;
+}
+
+bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
+ Fstab fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+ return false;
+ }
+ const auto lowerdir = kLowerdirOption + mount_point;
+ for (const auto& entry : fstab) {
+ if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
+ if (mount_point != entry.mount_point) continue;
+ if (!overlay_only) return true;
+ const auto options = android::base::Split(entry.fs_options, ",");
+ for (const auto& opt : options) {
+ if (opt == lowerdir) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.h b/fs_mgr/fs_mgr_overlayfs_mount.h
new file mode 100644
index 0000000..ae3ea84
--- /dev/null
+++ b/fs_mgr/fs_mgr_overlayfs_mount.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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 <string>
+
+#include <fstab/fstab.h>
+
+bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
+bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
+android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
+
+#if ALLOW_ADBD_DISABLE_VERITY
+constexpr bool kAllowOverlayfs = true;
+#else
+constexpr bool kAllowOverlayfs = false;
+#endif
+
+class AutoSetFsCreateCon final {
+ public:
+ AutoSetFsCreateCon() {}
+ AutoSetFsCreateCon(const std::string& context) { Set(context); }
+ ~AutoSetFsCreateCon() { Restore(); }
+
+ bool Ok() const { return ok_; }
+ bool Set(const std::string& context);
+ bool Restore();
+
+ private:
+ bool ok_ = false;
+ bool restored_ = false;
+};
+
+constexpr auto kScratchMountPoint = "/mnt/scratch";
+constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
+
+constexpr auto kUpperName = "upper";
+constexpr auto kWorkName = "work";
+constexpr auto kOverlayTopDir = "/overlay";
+
+bool fs_mgr_is_dsu_running();
+bool fs_mgr_in_recovery();
+bool fs_mgr_access(const std::string& path);
+bool fs_mgr_rw_access(const std::string& path);
+bool fs_mgr_filesystem_has_space(const std::string& mount_point);
+const std::string fs_mgr_mount_point(const std::string& mount_point);
+bool fs_mgr_overlayfs_umount_scratch();
+std::vector<const std::string> OverlayMountPoints();
diff --git a/fs_mgr/fs_mgr_priv_overlayfs.h b/fs_mgr/fs_mgr_priv_overlayfs.h
deleted file mode 100644
index 2033701..0000000
--- a/fs_mgr/fs_mgr_priv_overlayfs.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2022 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 <string>
-
-#include <fstab/fstab.h>
-
-bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
-bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
-android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
-
-// If "mount_point" is non-null, set up exactly one overlay.
-// If "mount_point" is null, setup any overlays.
-//
-// If |want_reboot| is non-null, and a reboot is needed to apply overlays, then
-// it will be true on return. The caller is responsible for initializing it.
-bool fs_mgr_overlayfs_setup(const android::fs_mgr::Fstab& fstab, const char* mount_point = nullptr,
- bool* want_reboot = nullptr, bool just_disabled_verity = true);
-
-enum class OverlayfsTeardownResult {
- Ok,
- Busy, // Indicates that overlays are still in use.
- Error
-};
-OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
- bool* want_reboot = nullptr);
-
-namespace android {
-namespace fs_mgr {
-
-void CleanupOldScratchFiles();
-
-} // namespace fs_mgr
-} // namespace android
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 5a9f391..4c45828 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -43,7 +43,8 @@
#include <libavb_user/libavb_user.h>
#include <libgsi/libgsid.h>
-#include "fs_mgr_priv_overlayfs.h"
+#include "fs_mgr_overlayfs_control.h"
+#include "fs_mgr_overlayfs_mount.h"
using namespace std::literals;
using android::fs_mgr::Fstab;
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index a914b53..9cb1546 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -101,6 +101,7 @@
bool SkipMountWithConfig(const std::string& skip_config, Fstab* fstab, bool verbose);
bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
+bool ReadFstabFromProcMounts(Fstab* fstab);
bool ReadFstabFromDt(Fstab* fstab, bool verbose = true);
bool ReadDefaultFstab(Fstab* fstab);
bool SkipMountingPartitions(Fstab* fstab, bool verbose = false);
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 9d1ce7d..8f35381 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -166,7 +166,6 @@
header_libs: [
"libupdate_engine_headers",
],
- export_include_dirs: ["include"],
}
cc_library_static {
@@ -184,6 +183,7 @@
"libsnapshot_cow/writer_base.cpp",
"libsnapshot_cow/writer_v2.cpp",
],
+ export_include_dirs: ["include"],
host_supported: true,
recovery_available: true,
ramdisk_available: true,
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index dd626bc..3a81f63 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -166,6 +166,13 @@
static constexpr uint8_t kCowReadAheadInProgress = 1;
static constexpr uint8_t kCowReadAheadDone = 2;
+static inline uint64_t GetCowOpSourceInfoData(const CowOperation* op) {
+ return op->source;
+}
+static inline bool GetCowOpSourceInfoCompression(const CowOperation* op) {
+ return op->compression != kCowCompressNone;
+}
+
struct CowFooter {
CowFooterOperation op;
uint8_t unused[64];
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 3890b17..f4ce52f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -73,8 +73,20 @@
// The operation pointer must derive from ICowOpIter::Get().
virtual ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
size_t ignore_bytes = 0) = 0;
+
+ // Get the absolute source offset, in bytes, of a CowOperation. Returns
+ // false if the operation does not read from source partitions.
+ virtual bool GetSourceOffset(const CowOperation* op, uint64_t* source_offset) = 0;
};
+static constexpr uint64_t GetBlockFromOffset(const CowHeader& header, uint64_t offset) {
+ return offset / header.block_size;
+}
+
+static constexpr uint64_t GetBlockRelativeOffset(const CowHeader& header, uint64_t offset) {
+ return offset % header.block_size;
+}
+
// Iterate over a sequence of COW operations. The iterator is bidirectional.
class ICowOpIter {
public:
@@ -119,6 +131,7 @@
bool VerifyMergeOps() override;
bool GetFooter(CowFooter* footer) override;
bool GetLastLabel(uint64_t* label) override;
+ bool GetSourceOffset(const CowOperation* op, uint64_t* source_offset) override;
// Create a CowOpIter object which contains footer_.num_ops
// CowOperation objects. Get() returns a unique CowOperation object
@@ -133,6 +146,7 @@
CowHeader& GetHeader() override { return header_; }
+ bool GetRawBytes(const CowOperation* op, void* buffer, size_t len, size_t* read);
bool GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read);
// Returns the total number of data ops that should be merged. This is the
@@ -154,6 +168,7 @@
bool ParseOps(std::optional<uint64_t> label);
bool PrepMergeOps();
uint64_t FindNumCopyops();
+ uint8_t GetCompressionType(const CowOperation* op);
android::base::unique_fd owned_fd_;
android::base::borrowed_fd fd_;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
index c2a7fdb..489669a 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
@@ -230,7 +230,7 @@
size_t seq_len = current_op.data_length / sizeof(uint32_t);
merge_op_blocks->resize(merge_op_blocks->size() + seq_len);
- if (!GetRawBytes(current_op.source, &merge_op_blocks->data()[num_seqs],
+ if (!GetRawBytes(¤t_op, &merge_op_blocks->data()[num_seqs],
current_op.data_length, &read)) {
PLOG(ERROR) << "Failed to read sequence op!";
return false;
@@ -312,19 +312,15 @@
std::unordered_map<uint64_t, const CowOperation*> overwritten_blocks;
while (!itr->AtEnd()) {
const auto& op = itr->Get();
- uint64_t block;
- bool offset;
- if (op->type == kCowCopyOp) {
- block = op->source;
- offset = false;
- } else if (op->type == kCowXorOp) {
- block = op->source / header_.block_size;
- offset = (op->source % header_.block_size) != 0;
- } else {
+ uint64_t offset;
+ if (!GetSourceOffset(op, &offset)) {
itr->Next();
continue;
}
+ uint64_t block = GetBlockFromOffset(header_, offset);
+ bool misaligned = (GetBlockRelativeOffset(header_, offset) != 0);
+
const CowOperation* overwrite = nullptr;
if (overwritten_blocks.count(block)) {
overwrite = overwritten_blocks[block];
@@ -332,7 +328,7 @@
<< op << "\noverwritten by previously merged op:\n"
<< *overwrite;
}
- if (offset && overwritten_blocks.count(block + 1)) {
+ if (misaligned && overwritten_blocks.count(block + 1)) {
overwrite = overwritten_blocks[block + 1];
LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
<< op << "\noverwritten by previously merged op:\n"
@@ -516,6 +512,18 @@
ignore_progress ? 0 : merge_op_start_);
}
+bool CowReader::GetRawBytes(const CowOperation* op, void* buffer, size_t len, size_t* read) {
+ switch (op->type) {
+ case kCowSequenceOp:
+ case kCowReplaceOp:
+ case kCowXorOp:
+ return GetRawBytes(GetCowOpSourceInfoData(op), buffer, len, read);
+ default:
+ LOG(ERROR) << "Cannot get raw bytes of non-data op: " << *op;
+ return false;
+ }
+}
+
bool CowReader::GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read) {
// Validate the offset, taking care to acknowledge possible overflow of offset+len.
if (offset < header_.prefix.header_size || offset >= fd_size_ - sizeof(CowFooter) ||
@@ -566,10 +574,14 @@
size_t remaining_;
};
+uint8_t CowReader::GetCompressionType(const CowOperation* op) {
+ return op->compression;
+}
+
ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
size_t ignore_bytes) {
std::unique_ptr<IDecompressor> decompressor;
- switch (op->compression) {
+ switch (GetCompressionType(op)) {
case kCowCompressNone:
break;
case kCowCompressGz:
@@ -589,7 +601,7 @@
}
break;
default:
- LOG(ERROR) << "Unknown compression type: " << op->compression;
+ LOG(ERROR) << "Unknown compression type: " << GetCompressionType(op);
return -1;
}
@@ -597,7 +609,7 @@
if (op->type == kCowXorOp) {
offset = data_loc_->at(op->new_block);
} else {
- offset = op->source;
+ offset = GetCowOpSourceInfoData(op);
}
if (!decompressor) {
@@ -610,5 +622,18 @@
return decompressor->Decompress(buffer, buffer_size, header_.block_size, ignore_bytes);
}
+bool CowReader::GetSourceOffset(const CowOperation* op, uint64_t* source_offset) {
+ switch (op->type) {
+ case kCowCopyOp:
+ *source_offset = GetCowOpSourceInfoData(op) * header_.block_size;
+ return true;
+ case kCowXorOp:
+ *source_offset = GetCowOpSourceInfoData(op);
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
index 148ecb0..a6dee4f 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
@@ -57,7 +57,7 @@
size_t count;
auto buffer = std::make_unique<uint8_t[]>(op->data_length);
- if (!reader.GetRawBytes(op->source, buffer.get(), op->data_length, &count)) {
+ if (!reader.GetRawBytes(op, buffer.get(), op->data_length, &count)) {
std::cerr << "Failed to read at all!\n";
} else {
std::cout << "The Block data is:\n";
@@ -199,7 +199,7 @@
std::vector<uint32_t> merge_op_blocks;
size_t seq_len = op->data_length / sizeof(uint32_t);
merge_op_blocks.resize(seq_len);
- if (!reader.GetRawBytes(op->source, merge_op_blocks.data(), op->data_length, &read)) {
+ if (!reader.GetRawBytes(op, merge_op_blocks.data(), op->data_length, &read)) {
PLOG(ERROR) << "Failed to read sequence op!";
return false;
}
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
index f9cdbc0..a3e40d9 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
@@ -155,7 +155,12 @@
}
if (op) {
- chunk = op->source;
+ uint64_t source_offset;
+ if (!cow_->GetSourceOffset(op, &source_offset)) {
+ LOG(ERROR) << "GetSourceOffset failed in CompressedSnapshotReader for op: " << *op;
+ return false;
+ }
+ chunk = GetBlockFromOffset(cow_->GetHeader(), source_offset);
}
off64_t offset = (chunk * block_size_) + start_offset;
@@ -179,7 +184,12 @@
return -1;
}
- off64_t offset = op->source + start_offset;
+ uint64_t source_offset;
+ if (!cow_->GetSourceOffset(op, &source_offset)) {
+ LOG(ERROR) << "GetSourceOffset failed in CompressedSnapshotReader for op: " << *op;
+ return false;
+ }
+ off64_t offset = source_offset + start_offset;
std::string data(bytes_to_read, '\0');
if (!android::base::ReadFullyAtOffset(fd, data.data(), data.size(), offset)) {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
index 120b2c0..31b9a58 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
@@ -145,7 +145,7 @@
op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_EQ(op->compression, kCowCompressNone);
+ ASSERT_FALSE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->data_length, 4096);
ASSERT_EQ(op->new_block, 50);
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -224,10 +224,10 @@
op = iter->Get();
ASSERT_EQ(op->type, kCowXorOp);
- ASSERT_EQ(op->compression, kCowCompressNone);
+ ASSERT_FALSE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->data_length, 4096);
ASSERT_EQ(op->new_block, 50);
- ASSERT_EQ(op->source, 98314); // 4096 * 24 + 10
+ ASSERT_EQ(GetCowOpSourceInfoData(op), 98314); // 4096 * 24 + 10
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
ASSERT_EQ(sink, data);
@@ -283,7 +283,7 @@
std::string sink(data.size(), '\0');
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_EQ(op->compression, kCowCompressGz);
+ ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->data_length, 56); // compressed!
ASSERT_EQ(op->new_block, 50);
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -339,7 +339,7 @@
total_blocks += 1;
std::string sink(xor_data.size(), '\0');
ASSERT_EQ(op->new_block, 50);
- ASSERT_EQ(op->source, 98314); // 4096 * 24 + 10
+ ASSERT_EQ(GetCowOpSourceInfoData(op), 98314); // 4096 * 24 + 10
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
ASSERT_EQ(sink, xor_data);
}
@@ -528,7 +528,7 @@
std::string sink(data.size(), '\0');
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_EQ(op->compression, kCowCompressGz);
+ ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->data_length, 56); // compressed!
ASSERT_EQ(op->new_block, 50);
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -546,7 +546,7 @@
sink = {};
sink.resize(data2.size(), '\0');
- ASSERT_EQ(op->compression, kCowCompressGz);
+ ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->data_length, 41); // compressed!
ASSERT_EQ(op->new_block, 51);
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -591,7 +591,7 @@
auto op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_EQ(op->compression, kCowCompressGz);
+ ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->new_block, 51);
ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
}
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index fbea79b..09d35cf 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2490,9 +2490,6 @@
}
created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, name);
- remaining_time = GetRemainingTime(params.timeout_ms, begin);
- if (remaining_time.count() < 0) return false;
-
cow_device = new_cow_device;
}
@@ -2507,6 +2504,9 @@
// the user-space will not start the merge. We have to explicitly inform the
// daemon to resume the merge. Check ProcessUpdateState() call stack.
if (!UpdateUsesUserSnapshots(lock)) {
+ remaining_time = GetRemainingTime(params.timeout_ms, begin);
+ if (remaining_time.count() < 0) return false;
+
std::string path;
if (!MapSnapshot(lock, params.GetPartitionName(), base_device, cow_device, remaining_time,
&path)) {
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 9fe567a..a9b96e2 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -57,18 +57,20 @@
defaults: [
"fs_mgr_defaults",
],
+ local_include_dirs: ["include/"],
srcs: [
"dm-snapshot-merge/snapuserd.cpp",
"dm-snapshot-merge/snapuserd_worker.cpp",
"dm-snapshot-merge/snapuserd_readahead.cpp",
"snapuserd_buffer.cpp",
"user-space-merge/handler_manager.cpp",
+ "user-space-merge/read_worker.cpp",
"user-space-merge/snapuserd_core.cpp",
- "user-space-merge/snapuserd_dm_user.cpp",
"user-space-merge/snapuserd_merge.cpp",
"user-space-merge/snapuserd_readahead.cpp",
"user-space-merge/snapuserd_transitions.cpp",
"user-space-merge/snapuserd_verify.cpp",
+ "user-space-merge/worker.cpp",
],
static_libs: [
"libbase",
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
index da9bd11..978a7f2 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
@@ -508,7 +508,7 @@
// the merge of operations are done based on the ops present
// in the file.
//===========================================================
- uint64_t block_source = cow_op->source;
+ uint64_t block_source = GetCowOpSourceInfoData(cow_op);
if (prev_id.has_value()) {
if (dest_blocks.count(cow_op->new_block) || source_blocks.count(block_source)) {
break;
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp
index a32c2bf..d5fbe91 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp
@@ -172,7 +172,7 @@
}
void ReadAheadThread::CheckOverlap(const CowOperation* cow_op) {
- uint64_t source_block = cow_op->source;
+ uint64_t source_block = GetCowOpSourceInfoData(cow_op);
if (dest_blocks_.count(cow_op->new_block) || source_blocks_.count(source_block)) {
overlap_ = true;
}
@@ -191,7 +191,7 @@
// Get the first block with offset
const CowOperation* cow_op = GetRAOpIter();
CHECK_NE(cow_op, nullptr);
- *source_offset = cow_op->source;
+ *source_offset = GetCowOpSourceInfoData(cow_op);
if (cow_op->type == kCowCopyOp) {
*source_offset *= BLOCK_SZ;
}
@@ -210,7 +210,7 @@
while (!RAIterDone() && num_ops) {
const CowOperation* op = GetRAOpIter();
CHECK_NE(op, nullptr);
- uint64_t next_offset = op->source;
+ uint64_t next_offset = GetCowOpSourceInfoData(op);
if (op->type == kCowCopyOp) {
next_offset *= BLOCK_SZ;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
index 922df34..559dcc7 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
@@ -115,12 +115,13 @@
SNAP_LOG(ERROR) << "ReadFromBaseDevice: Failed to get payload buffer";
return false;
}
- SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
- << " Source: " << cow_op->source;
- uint64_t offset = cow_op->source;
- if (cow_op->type == kCowCopyOp) {
- offset *= BLOCK_SZ;
+ uint64_t offset;
+ if (!reader_->GetSourceOffset(cow_op, &offset)) {
+ SNAP_LOG(ERROR) << "ReadFromBaseDevice: Failed to get source offset";
+ return false;
}
+ SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
+ << " Source: " << offset;
if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SZ, offset)) {
SNAP_PLOG(ERROR) << "Copy op failed. Read from backing store: " << backing_store_device_
<< "at block :" << offset / BLOCK_SZ << " offset:" << offset % BLOCK_SZ;
@@ -508,7 +509,7 @@
if (read_ahead_buffer_map.find(cow_op->new_block) == read_ahead_buffer_map.end()) {
SNAP_LOG(ERROR)
<< " Block: " << cow_op->new_block << " not found in read-ahead cache"
- << " Source: " << cow_op->source;
+ << " Op: " << *cow_op;
return -1;
}
// If this is a final block merged in the read-ahead buffer
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
index bdba5c0..4105b4b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -18,7 +18,9 @@
#include <android-base/logging.h>
+#include "read_worker.h"
#include "snapuserd_core.h"
+#include "snapuserd_merge.h"
namespace android {
namespace snapshot {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp
similarity index 76%
rename from fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
rename to fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp
index 7858216..dd2996b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "read_worker.h"
+
#include "snapuserd_core.h"
namespace android {
@@ -23,59 +25,24 @@
using namespace android::dm;
using android::base::unique_fd;
-Worker::Worker(const std::string& cow_device, const std::string& backing_device,
- const std::string& control_device, const std::string& misc_name,
- const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd) {
- cow_device_ = cow_device;
- backing_store_device_ = backing_device;
- control_device_ = control_device;
- misc_name_ = misc_name;
- base_path_merge_ = base_path_merge;
- snapuserd_ = snapuserd;
+void ReadWorker::CloseFds() {
+ ctrl_fd_ = {};
+ backing_store_fd_ = {};
+ Worker::CloseFds();
}
-bool Worker::InitializeFds() {
- backing_store_fd_.reset(open(backing_store_device_.c_str(), O_RDONLY));
- if (backing_store_fd_ < 0) {
- SNAP_PLOG(ERROR) << "Open Failed: " << backing_store_device_;
- return false;
- }
-
- cow_fd_.reset(open(cow_device_.c_str(), O_RDWR));
- if (cow_fd_ < 0) {
- SNAP_PLOG(ERROR) << "Open Failed: " << cow_device_;
- return false;
- }
-
- ctrl_fd_.reset(open(control_device_.c_str(), O_RDWR));
- if (ctrl_fd_ < 0) {
- SNAP_PLOG(ERROR) << "Unable to open " << control_device_;
- return false;
- }
-
- // Base device used by merge thread
- base_path_merge_fd_.reset(open(base_path_merge_.c_str(), O_RDWR));
- if (base_path_merge_fd_ < 0) {
- SNAP_PLOG(ERROR) << "Open Failed: " << base_path_merge_;
- return false;
- }
-
- return true;
-}
-
-bool Worker::InitReader() {
- reader_ = snapuserd_->CloneReaderForWorker();
-
- if (!reader_->InitForMerge(std::move(cow_fd_))) {
- return false;
- }
- return true;
-}
+ReadWorker::ReadWorker(const std::string& cow_device, const std::string& backing_device,
+ const std::string& control_device, const std::string& misc_name,
+ const std::string& base_path_merge,
+ std::shared_ptr<SnapshotHandler> snapuserd)
+ : Worker(cow_device, misc_name, base_path_merge, snapuserd),
+ backing_store_device_(backing_device),
+ control_device_(control_device) {}
// Start the replace operation. This will read the
// internal COW format and if the block is compressed,
// it will be de-compressed.
-bool Worker::ProcessReplaceOp(const CowOperation* cow_op) {
+bool ReadWorker::ProcessReplaceOp(const CowOperation* cow_op) {
void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
if (!buffer) {
SNAP_LOG(ERROR) << "ProcessReplaceOp failed to allocate buffer";
@@ -88,18 +55,19 @@
return true;
}
-bool Worker::ReadFromSourceDevice(const CowOperation* cow_op) {
+bool ReadWorker::ReadFromSourceDevice(const CowOperation* cow_op) {
void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
if (buffer == nullptr) {
SNAP_LOG(ERROR) << "ReadFromBaseDevice: Failed to get payload buffer";
return false;
}
- SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
- << " Source: " << cow_op->source;
- uint64_t offset = cow_op->source;
- if (cow_op->type == kCowCopyOp) {
- offset *= BLOCK_SZ;
+ uint64_t offset;
+ if (!reader_->GetSourceOffset(cow_op, &offset)) {
+ SNAP_LOG(ERROR) << "ReadFromSourceDevice: Failed to get source offset";
+ return false;
}
+ SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
+ << " Op: " << *cow_op;
if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SZ, offset)) {
std::string op;
if (cow_op->type == kCowCopyOp)
@@ -117,7 +85,7 @@
// Start the copy operation. This will read the backing
// block device which is represented by cow_op->source.
-bool Worker::ProcessCopyOp(const CowOperation* cow_op) {
+bool ReadWorker::ProcessCopyOp(const CowOperation* cow_op) {
if (!ReadFromSourceDevice(cow_op)) {
return false;
}
@@ -125,7 +93,7 @@
return true;
}
-bool Worker::ProcessXorOp(const CowOperation* cow_op) {
+bool ReadWorker::ProcessXorOp(const CowOperation* cow_op) {
if (!ReadFromSourceDevice(cow_op)) {
return false;
}
@@ -152,7 +120,7 @@
return true;
}
-bool Worker::ProcessZeroOp() {
+bool ReadWorker::ProcessZeroOp() {
// Zero out the entire block
void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
if (buffer == nullptr) {
@@ -164,7 +132,7 @@
return true;
}
-bool Worker::ProcessOrderedOp(const CowOperation* cow_op) {
+bool ReadWorker::ProcessOrderedOp(const CowOperation* cow_op) {
void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
if (buffer == nullptr) {
SNAP_LOG(ERROR) << "ProcessOrderedOp: Failed to get payload buffer";
@@ -217,7 +185,7 @@
return false;
}
-bool Worker::ProcessCowOp(const CowOperation* cow_op) {
+bool ReadWorker::ProcessCowOp(const CowOperation* cow_op) {
if (cow_op == nullptr) {
SNAP_LOG(ERROR) << "ProcessCowOp: Invalid cow_op";
return false;
@@ -245,31 +213,28 @@
return false;
}
-void Worker::InitializeBufsink() {
- // Allocate the buffer which is used to communicate between
- // daemon and dm-user. The buffer comprises of header and a fixed payload.
- // If the dm-user requests a big IO, the IO will be broken into chunks
- // of PAYLOAD_BUFFER_SZ.
- size_t buf_size = sizeof(struct dm_user_header) + PAYLOAD_BUFFER_SZ;
- bufsink_.Initialize(buf_size);
-}
+bool ReadWorker::Init() {
+ if (!Worker::Init()) {
+ return false;
+ }
-bool Worker::Init() {
- InitializeBufsink();
+ backing_store_fd_.reset(open(backing_store_device_.c_str(), O_RDONLY));
+ if (backing_store_fd_ < 0) {
+ SNAP_PLOG(ERROR) << "Open Failed: " << backing_store_device_;
+ return false;
+ }
+
+ ctrl_fd_.reset(open(control_device_.c_str(), O_RDWR));
+ if (ctrl_fd_ < 0) {
+ SNAP_PLOG(ERROR) << "Unable to open " << control_device_;
+ return false;
+ }
+
xorsink_.Initialize(&bufsink_, BLOCK_SZ);
-
- if (!InitializeFds()) {
- return false;
- }
-
- if (!InitReader()) {
- return false;
- }
-
return true;
}
-bool Worker::RunThread() {
+bool ReadWorker::Run() {
SNAP_LOG(INFO) << "Processing snapshot I/O requests....";
if (setpriority(PRIO_PROCESS, gettid(), kNiceValueForMergeThreads)) {
@@ -289,26 +254,11 @@
return true;
}
-// Read Header from dm-user misc device. This gives
-// us the sector number for which IO is issued by dm-snapshot device
-bool Worker::ReadDmUserHeader() {
- if (!android::base::ReadFully(ctrl_fd_, bufsink_.GetBufPtr(), sizeof(struct dm_user_header))) {
- if (errno != ENOTBLK) {
- SNAP_PLOG(ERROR) << "Control-read failed";
- }
-
- SNAP_PLOG(DEBUG) << "ReadDmUserHeader failed....";
- return false;
- }
-
- return true;
-}
-
// Send the payload/data back to dm-user misc device.
-bool Worker::WriteDmUserPayload(size_t size, bool header_response) {
+bool ReadWorker::WriteDmUserPayload(size_t size) {
size_t payload_size = size;
void* buf = bufsink_.GetPayloadBufPtr();
- if (header_response) {
+ if (header_response_) {
payload_size += sizeof(struct dm_user_header);
buf = bufsink_.GetBufPtr();
}
@@ -318,10 +268,13 @@
return false;
}
+ // After the first header is sent in response to a request, we cannot
+ // send any additional headers.
+ header_response_ = false;
return true;
}
-bool Worker::ReadDataFromBaseDevice(sector_t sector, size_t read_size) {
+bool ReadWorker::ReadDataFromBaseDevice(sector_t sector, size_t read_size) {
CHECK(read_size <= BLOCK_SZ);
void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
@@ -340,20 +293,16 @@
return true;
}
-bool Worker::ReadAlignedSector(sector_t sector, size_t sz, bool header_response) {
- struct dm_user_header* header = bufsink_.GetHeaderPtr();
+bool ReadWorker::ReadAlignedSector(sector_t sector, size_t sz) {
size_t remaining_size = sz;
std::vector<std::pair<sector_t, const CowOperation*>>& chunk_vec = snapuserd_->GetChunkVec();
- bool io_error = false;
int ret = 0;
do {
// Process 1MB payload at a time
size_t read_size = std::min(PAYLOAD_BUFFER_SZ, remaining_size);
- header->type = DM_USER_RESP_SUCCESS;
size_t total_bytes_read = 0;
- io_error = false;
bufsink_.ResetBufferOffset();
while (read_size) {
@@ -371,7 +320,7 @@
// device.
if (!ReadDataFromBaseDevice(sector, size)) {
SNAP_LOG(ERROR) << "ReadDataFromBaseDevice failed";
- header->type = DM_USER_RESP_ERROR;
+ return false;
}
ret = size;
@@ -380,20 +329,10 @@
// process it.
if (!ProcessCowOp(it->second)) {
SNAP_LOG(ERROR) << "ProcessCowOp failed";
- header->type = DM_USER_RESP_ERROR;
- }
-
- ret = BLOCK_SZ;
- }
-
- // Just return the header if it is an error
- if (header->type == DM_USER_RESP_ERROR) {
- if (!RespondIOError(header_response)) {
return false;
}
- io_error = true;
- break;
+ ret = BLOCK_SZ;
}
read_size -= ret;
@@ -402,23 +341,19 @@
bufsink_.UpdateBufferOffset(ret);
}
- if (!io_error) {
- if (!WriteDmUserPayload(total_bytes_read, header_response)) {
- return false;
- }
-
- SNAP_LOG(DEBUG) << "WriteDmUserPayload success total_bytes_read: " << total_bytes_read
- << " header-response: " << header_response
- << " remaining_size: " << remaining_size;
- header_response = false;
- remaining_size -= total_bytes_read;
+ if (!WriteDmUserPayload(total_bytes_read)) {
+ return false;
}
- } while (remaining_size > 0 && !io_error);
+
+ SNAP_LOG(DEBUG) << "WriteDmUserPayload success total_bytes_read: " << total_bytes_read
+ << " remaining_size: " << remaining_size;
+ remaining_size -= total_bytes_read;
+ } while (remaining_size > 0);
return true;
}
-int Worker::ReadUnalignedSector(
+int ReadWorker::ReadUnalignedSector(
sector_t sector, size_t size,
std::vector<std::pair<sector_t, const CowOperation*>>::iterator& it) {
size_t skip_sector_size = 0;
@@ -453,9 +388,7 @@
return std::min(size, (BLOCK_SZ - skip_sector_size));
}
-bool Worker::ReadUnalignedSector(sector_t sector, size_t size) {
- struct dm_user_header* header = bufsink_.GetHeaderPtr();
- header->type = DM_USER_RESP_SUCCESS;
+bool ReadWorker::ReadUnalignedSector(sector_t sector, size_t size) {
bufsink_.ResetBufferOffset();
std::vector<std::pair<sector_t, const CowOperation*>>& chunk_vec = snapuserd_->GetChunkVec();
@@ -483,7 +416,6 @@
// to any COW ops. In that case, we just need to read from the base
// device.
bool merge_complete = false;
- bool header_response = true;
if (it == chunk_vec.end()) {
if (chunk_vec.size() > 0) {
// I/O request beyond the last mapped sector
@@ -502,7 +434,7 @@
--it;
}
} else {
- return ReadAlignedSector(sector, size, header_response);
+ return ReadAlignedSector(sector, size);
}
loff_t requested_offset = sector << SECTOR_SHIFT;
@@ -536,7 +468,7 @@
if (ret < 0) {
SNAP_LOG(ERROR) << "ReadUnalignedSector failed for sector: " << sector
<< " size: " << size << " it->sector: " << it->first;
- return RespondIOError(header_response);
+ return false;
}
remaining_size -= ret;
@@ -544,14 +476,13 @@
sector += (ret >> SECTOR_SHIFT);
// Send the data back
- if (!WriteDmUserPayload(total_bytes_read, header_response)) {
+ if (!WriteDmUserPayload(total_bytes_read)) {
return false;
}
- header_response = false;
// If we still have pending data to be processed, this will be aligned I/O
if (remaining_size) {
- return ReadAlignedSector(sector, remaining_size, header_response);
+ return ReadAlignedSector(sector, remaining_size);
}
} else {
// This is all about handling I/O request to be routed to base device
@@ -565,21 +496,21 @@
CHECK(diff_size <= BLOCK_SZ);
if (remaining_size < diff_size) {
if (!ReadDataFromBaseDevice(sector, remaining_size)) {
- return RespondIOError(header_response);
+ return false;
}
total_bytes_read += remaining_size;
- if (!WriteDmUserPayload(total_bytes_read, header_response)) {
+ if (!WriteDmUserPayload(total_bytes_read)) {
return false;
}
} else {
if (!ReadDataFromBaseDevice(sector, diff_size)) {
- return RespondIOError(header_response);
+ return false;
}
total_bytes_read += diff_size;
- if (!WriteDmUserPayload(total_bytes_read, header_response)) {
+ if (!WriteDmUserPayload(total_bytes_read)) {
return false;
}
@@ -587,17 +518,16 @@
size_t num_sectors_read = (diff_size >> SECTOR_SHIFT);
sector += num_sectors_read;
CHECK(IsBlockAligned(sector << SECTOR_SHIFT));
- header_response = false;
// If we still have pending data to be processed, this will be aligned I/O
- return ReadAlignedSector(sector, remaining_size, header_response);
+ return ReadAlignedSector(sector, remaining_size);
}
}
return true;
}
-bool Worker::RespondIOError(bool header_response) {
+void ReadWorker::RespondIOError() {
struct dm_user_header* header = bufsink_.GetHeaderPtr();
header->type = DM_USER_RESP_ERROR;
// This is an issue with the dm-user interface. There
@@ -609,18 +539,12 @@
// this back to dm-user.
//
// TODO: Fix the interface
- CHECK(header_response);
+ CHECK(header_response_);
- if (!WriteDmUserPayload(0, header_response)) {
- return false;
- }
-
- // There is no need to process further as we have already seen
- // an I/O error
- return true;
+ WriteDmUserPayload(0);
}
-bool Worker::DmuserReadRequest() {
+bool ReadWorker::DmuserReadRequest() {
struct dm_user_header* header = bufsink_.GetHeaderPtr();
// Unaligned I/O request
@@ -628,13 +552,19 @@
return ReadUnalignedSector(header->sector, header->len);
}
- return ReadAlignedSector(header->sector, header->len, true);
+ return ReadAlignedSector(header->sector, header->len);
}
-bool Worker::ProcessIORequest() {
+bool ReadWorker::ProcessIORequest() {
+ // Read Header from dm-user misc device. This gives
+ // us the sector number for which IO is issued by dm-snapshot device
struct dm_user_header* header = bufsink_.GetHeaderPtr();
+ if (!android::base::ReadFully(ctrl_fd_, header, sizeof(*header))) {
+ if (errno != ENOTBLK) {
+ SNAP_PLOG(ERROR) << "Control-read failed";
+ }
- if (!ReadDmUserHeader()) {
+ SNAP_PLOG(DEBUG) << "ReadDmUserHeader failed....";
return false;
}
@@ -644,24 +574,34 @@
SNAP_LOG(DEBUG) << "Daemon: msg->type: " << std::dec << header->type;
SNAP_LOG(DEBUG) << "Daemon: msg->flags: " << std::dec << header->flags;
- switch (header->type) {
- case DM_USER_REQ_MAP_READ: {
- if (!DmuserReadRequest()) {
- return false;
- }
- break;
- }
+ // Use the same header buffer as the response header.
+ int request_type = header->type;
+ header->type = DM_USER_RESP_SUCCESS;
+ header_response_ = true;
- case DM_USER_REQ_MAP_WRITE: {
+ bool ok;
+ switch (request_type) {
+ case DM_USER_REQ_MAP_READ:
+ ok = DmuserReadRequest();
+ break;
+
+ case DM_USER_REQ_MAP_WRITE:
// TODO: We should not get any write request
// to dm-user as we mount all partitions
// as read-only. Need to verify how are TRIM commands
// handled during mount.
- return false;
- }
+ ok = false;
+ break;
+
+ default:
+ ok = false;
+ break;
}
- return true;
+ if (!ok && header->type != DM_USER_RESP_ERROR) {
+ RespondIOError();
+ }
+ return ok;
}
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.h
new file mode 100644
index 0000000..c3a4c34
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/read_worker.h
@@ -0,0 +1,70 @@
+// Copyright (C) 2023 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 <utility>
+#include <vector>
+
+#include "worker.h"
+
+namespace android {
+namespace snapshot {
+
+class ReadWorker : public Worker {
+ public:
+ ReadWorker(const std::string& cow_device, const std::string& backing_device,
+ const std::string& control_device, const std::string& misc_name,
+ const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd);
+
+ bool Run();
+ bool Init() override;
+ void CloseFds() override;
+
+ private:
+ // Functions interacting with dm-user
+ bool ProcessIORequest();
+ bool WriteDmUserPayload(size_t size);
+ bool DmuserReadRequest();
+ void RespondIOError();
+
+ bool ProcessCowOp(const CowOperation* cow_op);
+ bool ProcessXorOp(const CowOperation* cow_op);
+ bool ProcessOrderedOp(const CowOperation* cow_op);
+ bool ProcessCopyOp(const CowOperation* cow_op);
+ bool ProcessReplaceOp(const CowOperation* cow_op);
+ bool ProcessZeroOp();
+
+ bool ReadAlignedSector(sector_t sector, size_t sz);
+ bool ReadUnalignedSector(sector_t sector, size_t size);
+ int ReadUnalignedSector(sector_t sector, size_t size,
+ std::vector<std::pair<sector_t, const CowOperation*>>::iterator& it);
+ bool ReadFromSourceDevice(const CowOperation* cow_op);
+ bool ReadDataFromBaseDevice(sector_t sector, size_t read_size);
+
+ constexpr bool IsBlockAligned(size_t size) { return ((size & (BLOCK_SZ - 1)) == 0); }
+ constexpr sector_t ChunkToSector(chunk_t chunk) { return chunk << CHUNK_SHIFT; }
+
+ std::string backing_store_device_;
+ unique_fd backing_store_fd_;
+
+ std::string control_device_;
+ unique_fd ctrl_fd_;
+
+ XorSink xorsink_;
+ bool header_response_ = false;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
index 8e1212b..e52d752 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -23,6 +23,9 @@
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
+#include "read_worker.h"
+#include "snapuserd_merge.h"
+
namespace android {
namespace snapshot {
@@ -46,9 +49,8 @@
bool SnapshotHandler::InitializeWorkers() {
for (int i = 0; i < num_worker_threads_; i++) {
- std::unique_ptr<Worker> wt =
- std::make_unique<Worker>(cow_device_, backing_store_device_, control_device_,
- misc_name_, base_path_merge_, GetSharedPtr());
+ auto wt = std::make_unique<ReadWorker>(cow_device_, backing_store_device_, control_device_,
+ misc_name_, base_path_merge_, GetSharedPtr());
if (!wt->Init()) {
SNAP_LOG(ERROR) << "Thread initialization failed";
return false;
@@ -57,8 +59,8 @@
worker_threads_.push_back(std::move(wt));
}
- merge_thread_ = std::make_unique<Worker>(cow_device_, backing_store_device_, control_device_,
- misc_name_, base_path_merge_, GetSharedPtr());
+ merge_thread_ = std::make_unique<MergeWorker>(cow_device_, misc_name_, base_path_merge_,
+ GetSharedPtr());
read_ahead_thread_ = std::make_unique<ReadAhead>(cow_device_, backing_store_device_, misc_name_,
GetSharedPtr());
@@ -312,11 +314,11 @@
// Launch worker threads
for (int i = 0; i < worker_threads_.size(); i++) {
threads.emplace_back(
- std::async(std::launch::async, &Worker::RunThread, worker_threads_[i].get()));
+ std::async(std::launch::async, &ReadWorker::Run, worker_threads_[i].get()));
}
std::future<bool> merge_thread =
- std::async(std::launch::async, &Worker::RunMergeThread, merge_thread_.get());
+ std::async(std::launch::async, &MergeWorker::Run, merge_thread_.get());
// Now that the worker threads are up, scan the partitions.
if (perform_verification_) {
@@ -452,5 +454,11 @@
return update_verify_->CheckPartitionVerification();
}
+void SnapshotHandler::FreeResources() {
+ worker_threads_.clear();
+ read_ahead_thread_ = nullptr;
+ merge_thread_ = nullptr;
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index c16ad24..cdc38c0 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -75,7 +75,8 @@
READ_AHEAD_FAILURE,
};
-class SnapshotHandler;
+class MergeWorker;
+class ReadWorker;
enum class MERGE_GROUP_STATE {
GROUP_MERGE_PENDING,
@@ -98,102 +99,6 @@
: merge_state_(state), num_ios_in_progress(n_ios) {}
};
-class Worker {
- public:
- Worker(const std::string& cow_device, const std::string& backing_device,
- const std::string& control_device, const std::string& misc_name,
- const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd);
- bool RunThread();
- bool RunMergeThread();
- bool Init();
-
- private:
- // Initialization
- void InitializeBufsink();
- bool InitializeFds();
- bool InitReader();
- void CloseFds() {
- ctrl_fd_ = {};
- backing_store_fd_ = {};
- base_path_merge_fd_ = {};
- }
-
- // Functions interacting with dm-user
- bool ReadDmUserHeader();
- bool WriteDmUserPayload(size_t size, bool header_response);
- bool DmuserReadRequest();
-
- // IO Path
- bool ProcessIORequest();
- bool IsBlockAligned(size_t size) { return ((size & (BLOCK_SZ - 1)) == 0); }
-
- bool ReadDataFromBaseDevice(sector_t sector, size_t read_size);
- bool ReadFromSourceDevice(const CowOperation* cow_op);
-
- bool ReadAlignedSector(sector_t sector, size_t sz, bool header_response);
- bool ReadUnalignedSector(sector_t sector, size_t size);
- int ReadUnalignedSector(sector_t sector, size_t size,
- std::vector<std::pair<sector_t, const CowOperation*>>::iterator& it);
- bool RespondIOError(bool header_response);
-
- // Processing COW operations
- bool ProcessCowOp(const CowOperation* cow_op);
- bool ProcessReplaceOp(const CowOperation* cow_op);
- bool ProcessZeroOp();
-
- // Handles Copy and Xor
- bool ProcessCopyOp(const CowOperation* cow_op);
- bool ProcessXorOp(const CowOperation* cow_op);
- bool ProcessOrderedOp(const CowOperation* cow_op);
-
- // Merge related ops
- bool Merge();
- bool AsyncMerge();
- bool SyncMerge();
- bool MergeOrderedOps();
- bool MergeOrderedOpsAsync();
- bool MergeReplaceZeroOps();
- int PrepareMerge(uint64_t* source_offset, int* pending_ops,
- std::vector<const CowOperation*>* replace_zero_vec = nullptr);
-
- sector_t ChunkToSector(chunk_t chunk) { return chunk << CHUNK_SHIFT; }
- chunk_t SectorToChunk(sector_t sector) { return sector >> CHUNK_SHIFT; }
-
- bool InitializeIouring();
- void FinalizeIouring();
-
- std::unique_ptr<CowReader> reader_;
- BufferSink bufsink_;
- XorSink xorsink_;
-
- std::string cow_device_;
- std::string backing_store_device_;
- std::string control_device_;
- std::string misc_name_;
- std::string base_path_merge_;
-
- unique_fd cow_fd_;
- unique_fd backing_store_fd_;
- unique_fd base_path_merge_fd_;
- unique_fd ctrl_fd_;
-
- std::unique_ptr<ICowOpIter> cowop_iter_;
- size_t ra_block_index_ = 0;
- uint64_t blocks_merged_in_group_ = 0;
- bool merge_async_ = false;
- // Queue depth of 8 seems optimal. We don't want
- // to have a huge depth as it may put more memory pressure
- // on the kernel worker threads given that we use
- // IOSQE_ASYNC flag - ASYNC flags can potentially
- // result in EINTR; Since we don't restart
- // syscalls and fallback to synchronous I/O, we
- // don't want huge queue depth
- int queue_depth_ = 8;
- std::unique_ptr<struct io_uring> ring_;
-
- std::shared_ptr<SnapshotHandler> snapuserd_;
-};
-
class SnapshotHandler : public std::enable_shared_from_this<SnapshotHandler> {
public:
SnapshotHandler(std::string misc_name, std::string cow_device, std::string backing_device,
@@ -212,11 +117,7 @@
bool CommitMerge(int num_merge_ops);
void CloseFds() { cow_fd_ = {}; }
- void FreeResources() {
- worker_threads_.clear();
- read_ahead_thread_ = nullptr;
- merge_thread_ = nullptr;
- }
+ void FreeResources();
bool InitializeWorkers();
std::unique_ptr<CowReader> CloneReaderForWorker();
@@ -315,7 +216,7 @@
void* mapped_addr_;
size_t total_mapped_addr_length_;
- std::vector<std::unique_ptr<Worker>> worker_threads_;
+ std::vector<std::unique_ptr<ReadWorker>> worker_threads_;
// Read-ahead related
bool populate_data_from_cow_ = false;
bool ra_thread_ = false;
@@ -330,7 +231,7 @@
// Merge Block state
std::vector<std::unique_ptr<MergeGroupState>> merge_blk_state_;
- std::unique_ptr<Worker> merge_thread_;
+ std::unique_ptr<MergeWorker> merge_thread_;
double merge_completion_percentage_;
bool merge_initiated_ = false;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp
index ce95b76..563f6ad 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "snapuserd_merge.h"
#include "snapuserd_core.h"
@@ -23,8 +24,13 @@
using namespace android::dm;
using android::base::unique_fd;
-int Worker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
- std::vector<const CowOperation*>* replace_zero_vec) {
+MergeWorker::MergeWorker(const std::string& cow_device, const std::string& misc_name,
+ const std::string& base_path_merge,
+ std::shared_ptr<SnapshotHandler> snapuserd)
+ : Worker(cow_device, misc_name, base_path_merge, snapuserd) {}
+
+int MergeWorker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
+ std::vector<const CowOperation*>* replace_zero_vec) {
int num_ops = *pending_ops;
int nr_consecutive = 0;
bool checkOrderedOp = (replace_zero_vec == nullptr);
@@ -70,7 +76,7 @@
return nr_consecutive;
}
-bool Worker::MergeReplaceZeroOps() {
+bool MergeWorker::MergeReplaceZeroOps() {
// Flush after merging 2MB. Since all ops are independent and there is no
// dependency between COW ops, we will flush the data and the number
// of ops merged in COW block device. If there is a crash, we will
@@ -99,17 +105,20 @@
for (size_t i = 0; i < replace_zero_vec.size(); i++) {
const CowOperation* cow_op = replace_zero_vec[i];
+
+ void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
+ if (!buffer) {
+ SNAP_LOG(ERROR) << "Failed to acquire buffer in merge";
+ return false;
+ }
if (cow_op->type == kCowReplaceOp) {
- if (!ProcessReplaceOp(cow_op)) {
- SNAP_LOG(ERROR) << "Merge - ReplaceOp failed for block: " << cow_op->new_block;
+ if (!reader_->ReadData(cow_op, buffer, BLOCK_SZ)) {
+ SNAP_LOG(ERROR) << "Failed to read COW in merge";
return false;
}
} else {
CHECK(cow_op->type == kCowZeroOp);
- if (!ProcessZeroOp()) {
- SNAP_LOG(ERROR) << "Merge ZeroOp failed.";
- return false;
- }
+ memset(buffer, 0, BLOCK_SZ);
}
bufsink_.UpdateBufferOffset(BLOCK_SZ);
@@ -149,7 +158,7 @@
if (snapuserd_->IsIOTerminated()) {
SNAP_LOG(ERROR)
- << "MergeReplaceZeroOps: Worker threads terminated - shutting down merge";
+ << "MergeReplaceZeroOps: MergeWorker threads terminated - shutting down merge";
return false;
}
}
@@ -173,7 +182,7 @@
return true;
}
-bool Worker::MergeOrderedOpsAsync() {
+bool MergeWorker::MergeOrderedOpsAsync() {
void* mapped_addr = snapuserd_->GetMappedAddr();
void* read_ahead_buffer =
static_cast<void*>((char*)mapped_addr + snapuserd_->GetBufferDataOffset());
@@ -354,7 +363,7 @@
return true;
}
-bool Worker::MergeOrderedOps() {
+bool MergeWorker::MergeOrderedOps() {
void* mapped_addr = snapuserd_->GetMappedAddr();
void* read_ahead_buffer =
static_cast<void*>((char*)mapped_addr + snapuserd_->GetBufferDataOffset());
@@ -439,7 +448,7 @@
return true;
}
-bool Worker::AsyncMerge() {
+bool MergeWorker::AsyncMerge() {
if (!MergeOrderedOpsAsync()) {
SNAP_LOG(ERROR) << "MergeOrderedOpsAsync failed - Falling back to synchronous I/O";
// Reset the iter so that we retry the merge
@@ -455,7 +464,7 @@
return true;
}
-bool Worker::SyncMerge() {
+bool MergeWorker::SyncMerge() {
if (!MergeOrderedOps()) {
SNAP_LOG(ERROR) << "Merge failed for ordered ops";
return false;
@@ -465,7 +474,7 @@
return true;
}
-bool Worker::Merge() {
+bool MergeWorker::Merge() {
cowop_iter_ = reader_->GetOpIter(true);
bool retry = false;
@@ -511,7 +520,7 @@
return true;
}
-bool Worker::InitializeIouring() {
+bool MergeWorker::InitializeIouring() {
if (!snapuserd_->IsIouringSupported()) {
return false;
}
@@ -530,13 +539,13 @@
return true;
}
-void Worker::FinalizeIouring() {
+void MergeWorker::FinalizeIouring() {
if (merge_async_) {
io_uring_queue_exit(ring_.get());
}
}
-bool Worker::RunMergeThread() {
+bool MergeWorker::Run() {
SNAP_LOG(DEBUG) << "Waiting for merge begin...";
if (!snapuserd_->WaitForMergeBegin()) {
SNAP_LOG(ERROR) << "Merge terminated early...";
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.h
new file mode 100644
index 0000000..f35147f
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 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 "worker.h"
+
+#include <liburing.h>
+
+namespace android {
+namespace snapshot {
+
+class MergeWorker : public Worker {
+ public:
+ MergeWorker(const std::string& cow_device, const std::string& misc_name,
+ const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd);
+ bool Run();
+
+ private:
+ int PrepareMerge(uint64_t* source_offset, int* pending_ops,
+ std::vector<const CowOperation*>* replace_zero_vec = nullptr);
+ bool MergeReplaceZeroOps();
+ bool MergeOrderedOps();
+ bool MergeOrderedOpsAsync();
+ bool Merge();
+ bool AsyncMerge();
+ bool SyncMerge();
+ bool InitializeIouring();
+ void FinalizeIouring();
+
+ private:
+ std::unique_ptr<ICowOpIter> cowop_iter_;
+ std::unique_ptr<struct io_uring> ring_;
+ size_t ra_block_index_ = 0;
+ uint64_t blocks_merged_in_group_ = 0;
+ bool merge_async_ = false;
+ // Queue depth of 8 seems optimal. We don't want
+ // to have a huge depth as it may put more memory pressure
+ // on the kernel worker threads given that we use
+ // IOSQE_ASYNC flag - ASYNC flags can potentially
+ // result in EINTR; Since we don't restart
+ // syscalls and fallback to synchronous I/O, we
+ // don't want huge queue depth
+ int queue_depth_ = 8;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
index af24286..399f7b8 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
@@ -34,14 +34,17 @@
}
void ReadAhead::CheckOverlap(const CowOperation* cow_op) {
- uint64_t source_block = cow_op->source;
- uint64_t source_offset = 0;
- if (cow_op->type == kCowXorOp) {
- source_block /= BLOCK_SZ;
- source_offset = cow_op->source % BLOCK_SZ;
+ uint64_t source_offset;
+ if (!reader_->GetSourceOffset(cow_op, &source_offset)) {
+ SNAP_LOG(ERROR) << "ReadAhead operation has no source offset: " << *cow_op;
+ return;
}
+
+ uint64_t source_block = GetBlockFromOffset(header_, source_offset);
+ bool misaligned = (GetBlockRelativeOffset(header_, source_offset) != 0);
+
if (dest_blocks_.count(cow_op->new_block) || source_blocks_.count(source_block) ||
- (source_offset > 0 && source_blocks_.count(source_block + 1))) {
+ (misaligned && source_blocks_.count(source_block + 1))) {
overlap_ = true;
}
@@ -66,11 +69,12 @@
// Get the first block with offset
const CowOperation* cow_op = GetRAOpIter();
- *source_offset = cow_op->source;
- if (cow_op->type == kCowCopyOp) {
- *source_offset *= BLOCK_SZ;
- } else if (cow_op->type == kCowXorOp) {
+ if (!reader_->GetSourceOffset(cow_op, source_offset)) {
+ SNAP_LOG(ERROR) << "PrepareNextReadAhead operation has no source offset: " << *cow_op;
+ return nr_consecutive;
+ }
+ if (cow_op->type == kCowXorOp) {
xor_op_vec.push_back(cow_op);
}
@@ -88,10 +92,10 @@
*/
while (!RAIterDone() && num_ops) {
const CowOperation* op = GetRAOpIter();
- uint64_t next_offset = op->source;
-
- if (cow_op->type == kCowCopyOp) {
- next_offset *= BLOCK_SZ;
+ uint64_t next_offset;
+ if (!reader_->GetSourceOffset(op, &next_offset)) {
+ SNAP_LOG(ERROR) << "PrepareNextReadAhead operation has no source offset: " << *cow_op;
+ break;
}
// Check for consecutive blocks
@@ -803,6 +807,7 @@
if (!reader_->InitForMerge(std::move(cow_fd_))) {
return false;
}
+ header_ = reader_->GetHeader();
return true;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
index 5e94de0..d3ba126 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
@@ -85,6 +85,7 @@
std::shared_ptr<SnapshotHandler> snapuserd_;
std::unique_ptr<CowReader> reader_;
+ CowHeader header_;
std::unordered_set<uint64_t> dest_blocks_;
std::unordered_set<uint64_t> source_blocks_;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/worker.cpp
new file mode 100644
index 0000000..aa15630
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/worker.cpp
@@ -0,0 +1,80 @@
+// Copyright (C) 2023 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.
+
+#include "worker.h"
+
+#include "snapuserd_core.h"
+
+namespace android {
+namespace snapshot {
+
+Worker::Worker(const std::string& cow_device, const std::string& misc_name,
+ const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd) {
+ cow_device_ = cow_device;
+ misc_name_ = misc_name;
+ base_path_merge_ = base_path_merge;
+ snapuserd_ = snapuserd;
+}
+
+void Worker::InitializeBufsink() {
+ // Allocate the buffer which is used to communicate between
+ // daemon and dm-user. The buffer comprises of header and a fixed payload.
+ // If the dm-user requests a big IO, the IO will be broken into chunks
+ // of PAYLOAD_BUFFER_SZ.
+ size_t buf_size = sizeof(struct dm_user_header) + PAYLOAD_BUFFER_SZ;
+ bufsink_.Initialize(buf_size);
+}
+
+bool Worker::Init() {
+ InitializeBufsink();
+
+ if (!InitializeFds()) {
+ return false;
+ }
+
+ if (!InitReader()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool Worker::InitReader() {
+ reader_ = snapuserd_->CloneReaderForWorker();
+
+ if (!reader_->InitForMerge(std::move(cow_fd_))) {
+ return false;
+ }
+ return true;
+}
+
+bool Worker::InitializeFds() {
+ cow_fd_.reset(open(cow_device_.c_str(), O_RDWR));
+ if (cow_fd_ < 0) {
+ SNAP_PLOG(ERROR) << "Open Failed: " << cow_device_;
+ return false;
+ }
+
+ // Base device used by merge thread
+ base_path_merge_fd_.reset(open(base_path_merge_.c_str(), O_RDWR));
+ if (base_path_merge_fd_ < 0) {
+ SNAP_PLOG(ERROR) << "Open Failed: " << base_path_merge_;
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/worker.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/worker.h
new file mode 100644
index 0000000..813b159
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/worker.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2023 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 <stddef.h>
+
+#include <memory>
+#include <string>
+
+#include <android-base/unique_fd.h>
+#include <libsnapshot/cow_reader.h>
+#include <snapuserd/snapuserd_buffer.h>
+#include <snapuserd/snapuserd_kernel.h>
+
+namespace android {
+namespace snapshot {
+
+using android::base::unique_fd;
+
+class SnapshotHandler;
+
+class Worker {
+ public:
+ Worker(const std::string& cow_device, const std::string& misc_name,
+ const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd);
+ virtual ~Worker() = default;
+
+ virtual bool Init();
+
+ protected:
+ // Initialization
+ void InitializeBufsink();
+ bool InitializeFds();
+ bool InitReader();
+ virtual void CloseFds() { base_path_merge_fd_ = {}; }
+
+ std::unique_ptr<CowReader> reader_;
+ BufferSink bufsink_;
+
+ std::string misc_name_; // Needed for SNAP_LOG.
+
+ unique_fd base_path_merge_fd_;
+
+ std::shared_ptr<SnapshotHandler> snapuserd_;
+
+ private:
+ std::string cow_device_;
+ std::string base_path_merge_;
+ unique_fd cow_fd_;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/init/Android.bp b/init/Android.bp
index f62d7b7..4416b9d 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -166,11 +166,9 @@
"libbootloader_message",
"libc++fs",
"libcgrouprc_format",
- "libfsverity_init",
"liblmkd_utils",
"liblz4",
"libzstd",
- "libmini_keyctl_static",
"libmodprobe",
"libprocinfo",
"libprotobuf-cpp-lite",
@@ -214,8 +212,8 @@
visibility: [":__subpackages__"],
}
-cc_library_static {
- name: "libinit",
+cc_defaults {
+ name: "libinit_defaults",
recovery_available: true,
defaults: [
"init_defaults",
@@ -228,7 +226,6 @@
],
whole_static_libs: [
"libcap",
- "libcom.android.sysprop.apex",
"libcom.android.sysprop.init",
],
header_libs: ["bootimg_headers"],
@@ -252,10 +249,17 @@
],
},
},
- visibility: [
- "//system/apex/apexd",
- "//frameworks/native/cmds/installd",
- ],
+}
+
+cc_library_static {
+ name: "libinit",
+ defaults: ["libinit_defaults"],
+}
+
+cc_library_static {
+ name: "libinit.microdroid",
+ defaults: ["libinit_defaults"],
+ cflags: ["-DMICRODROID=1"],
}
phony {
@@ -270,7 +274,6 @@
recovery_available: true,
stem: "init",
defaults: ["init_defaults"],
- static_libs: ["libinit"],
srcs: ["main.cpp"],
symlinks: ["ueventd"],
target: {
@@ -309,12 +312,14 @@
cc_binary {
name: "init_second_stage",
defaults: ["init_second_stage_defaults"],
+ static_libs: ["libinit"],
}
cc_binary {
name: "init_second_stage.microdroid",
defaults: ["init_second_stage_defaults"],
- cflags: ["-DMICRODROID"],
+ static_libs: ["libinit.microdroid"],
+ cflags: ["-DMICRODROID=1"],
installable: false,
visibility: ["//packages/modules/Virtualization/microdroid"],
}
@@ -460,7 +465,7 @@
cc_binary {
name: "init_first_stage.microdroid",
defaults: ["init_first_stage_defaults"],
- cflags: ["-DMICRODROID"],
+ cflags: ["-DMICRODROID=1"],
installable: false,
}
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 585eca2..2176233 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -577,7 +577,7 @@
*
* return code is processed based on input code
*/
-static Result<void> queue_fs_event(int code, bool userdata_remount) {
+static Result<void> queue_fs_event(int code) {
if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
SetProperty("ro.crypto.state", "unsupported");
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
@@ -591,27 +591,9 @@
const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
return reboot_into_recovery(options);
/* If reboot worked, there is no return. */
- } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
- if (!FscryptInstallKeyring()) {
- return Error() << "FscryptInstallKeyring() failed";
- }
- SetProperty("ro.crypto.state", "encrypted");
-
- // Although encrypted, we have device key, so we do not need to
- // do anything different from the nonencrypted case.
- ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
- return {};
- } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
- if (!FscryptInstallKeyring()) {
- return Error() << "FscryptInstallKeyring() failed";
- }
- SetProperty("ro.crypto.state", "encrypted");
-
- // Although encrypted, vold has already set the device up, so we do not need to
- // do anything different from the nonencrypted case.
- ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
- return {};
- } else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
+ } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED ||
+ code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED ||
+ code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
if (!FscryptInstallKeyring()) {
return Error() << "FscryptInstallKeyring() failed";
}
@@ -683,7 +665,7 @@
if (queue_event) {
/* queue_fs_event will queue event based on mount_fstab return code
* and return processed return code*/
- auto queue_fs_result = queue_fs_event(mount_fstab_result.code, false);
+ auto queue_fs_result = queue_fs_event(mount_fstab_result.code);
if (!queue_fs_result.ok()) {
return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
}
@@ -1217,7 +1199,7 @@
"/metadata/userspacereboot/mount_info.txt");
trigger_shutdown("reboot,mount_userdata_failed");
}
- if (auto result = queue_fs_event(initial_mount_fstab_return_code, true); !result.ok()) {
+ if (auto result = queue_fs_event(initial_mount_fstab_return_code); !result.ok()) {
return Error() << "queue_fs_event() failed: " << result.error();
}
return {};
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index bff80c5..7fabbac 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -257,6 +257,16 @@
return BootMode::NORMAL_MODE;
}
+static std::unique_ptr<FirstStageMount> CreateFirstStageMount(const std::string& cmdline) {
+ auto ret = FirstStageMount::Create(cmdline);
+ if (ret.ok()) {
+ return std::move(*ret);
+ } else {
+ LOG(ERROR) << "Failed to create FirstStageMount : " << ret.error();
+ return nullptr;
+ }
+}
+
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@@ -347,6 +357,18 @@
LOG(INFO) << "init first stage started!";
+ // We only allow /vendor partition in debuggable Microdrod until it is verified during boot.
+ // TODO(b/285855436): remove this check.
+ if (IsMicrodroid()) {
+ bool mount_vendor =
+ cmdline.find("androidboot.microdroid.mount_vendor=1") != std::string::npos;
+ bool debuggable =
+ bootconfig.find("androidboot.microdroid.debuggable = \"1\"") != std::string::npos;
+ if (mount_vendor && !debuggable) {
+ LOG(FATAL) << "Attempted to mount /vendor partition for non-debuggable Microdroid VM";
+ }
+ }
+
auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
if (!old_root_dir) {
PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
@@ -381,12 +403,17 @@
<< module_elapse_time.count() << " ms";
}
+ std::unique_ptr<FirstStageMount> fsm;
+
bool created_devices = false;
if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
if (!IsRecoveryMode()) {
- created_devices = DoCreateDevices();
- if (!created_devices) {
- LOG(ERROR) << "Failed to create device nodes early";
+ fsm = CreateFirstStageMount(cmdline);
+ if (fsm) {
+ created_devices = fsm->DoCreateDevices();
+ if (!created_devices) {
+ LOG(ERROR) << "Failed to create device nodes early";
+ }
}
}
StartConsole(cmdline);
@@ -437,8 +464,23 @@
SwitchRoot("/first_stage_ramdisk");
}
- if (!DoFirstStageMount(!created_devices)) {
- LOG(FATAL) << "Failed to mount required partitions early ...";
+ if (IsRecoveryMode()) {
+ LOG(INFO) << "First stage mount skipped (recovery mode)";
+ } else {
+ if (!fsm) {
+ fsm = CreateFirstStageMount(cmdline);
+ }
+ if (!fsm) {
+ LOG(FATAL) << "FirstStageMount not available";
+ }
+
+ if (!created_devices && !fsm->DoCreateDevices()) {
+ LOG(FATAL) << "Failed to create devices required for first stage mount";
+ }
+
+ if (!fsm->DoFirstStageMount()) {
+ LOG(FATAL) << "Failed to mount required partitions early ...";
+ }
}
struct stat new_root_info;
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 07ce458..d0f68a8 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -76,21 +76,21 @@
// Class Declarations
// ------------------
-class FirstStageMount {
+class FirstStageMountVBootV2 : public FirstStageMount {
public:
- FirstStageMount(Fstab fstab);
- virtual ~FirstStageMount() = default;
+ friend void SetInitAvbVersionInRecovery();
- // The factory method to create a FirstStageMountVBootV2 instance.
- static Result<std::unique_ptr<FirstStageMount>> Create();
- bool DoCreateDevices(); // Creates devices and logical partitions from storage devices
- bool DoFirstStageMount(); // Mounts fstab entries read from device tree.
+ FirstStageMountVBootV2(Fstab fstab);
+ virtual ~FirstStageMountVBootV2() = default;
+
+ bool DoCreateDevices() override;
+ bool DoFirstStageMount() override;
+
+ private:
bool InitDevices();
-
- protected:
bool InitRequiredDevices(std::set<std::string> devices);
bool CreateLogicalPartitions();
- bool CreateSnapshotPartitions(android::snapshot::SnapshotManager* sm);
+ bool CreateSnapshotPartitions(SnapshotManager* sm);
bool MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
Fstab::iterator* end = nullptr);
@@ -106,9 +106,10 @@
// revocation check by DSU installation service.
void CopyDsuAvbKeys();
- // Pure virtual functions.
- virtual bool GetDmVerityDevices(std::set<std::string>* devices) = 0;
- virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
+ bool GetDmVerityDevices(std::set<std::string>* devices);
+ bool SetUpDmVerity(FstabEntry* fstab_entry);
+
+ bool InitAvbHandle();
bool need_dm_verity_;
bool dsu_not_on_userdata_ = false;
@@ -122,19 +123,6 @@
// Reads all AVB keys before chroot into /system, as they might be used
// later when mounting other partitions, e.g., /vendor and /product.
std::map<std::string, std::vector<std::string>> preload_avb_key_blobs_;
-};
-
-class FirstStageMountVBootV2 : public FirstStageMount {
- public:
- friend void SetInitAvbVersionInRecovery();
-
- FirstStageMountVBootV2(Fstab fstab);
- ~FirstStageMountVBootV2() override = default;
-
- protected:
- bool GetDmVerityDevices(std::set<std::string>* devices) override;
- bool SetUpDmVerity(FstabEntry* fstab_entry) override;
- bool InitAvbHandle();
std::vector<std::string> vbmeta_partitions_;
AvbUniquePtr avb_handle_;
@@ -150,7 +138,7 @@
return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
}
-static Result<Fstab> ReadFirstStageFstab() {
+static Result<Fstab> ReadFirstStageFstabAndroid() {
Fstab fstab;
if (!ReadFstabFromDt(&fstab)) {
if (ReadDefaultFstab(&fstab)) {
@@ -166,6 +154,24 @@
return fstab;
}
+// Note: this is a temporary solution to avoid blocking devs that depend on /vendor partition in
+// Microdroid. For the proper solution the /vendor fstab should probably be defined in the DT.
+// TODO(b/285855430): refactor this
+// TODO(b/285855436): verify key microdroid-vendor was signed with.
+// TODO(b/285855436): should be mounted on top of dm-verity device.
+static Result<Fstab> ReadFirstStageFstabMicrodroid(const std::string& cmdline) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return Error() << "failed to read fstab";
+ }
+ if (cmdline.find("androidboot.microdroid.mount_vendor=1") == std::string::npos) {
+ // We weren't asked to mount /vendor partition, filter it out from the fstab.
+ auto predicate = [](const auto& entry) { return entry.mount_point == "/vendor"; };
+ fstab.erase(std::remove_if(fstab.begin(), fstab.end(), predicate), fstab.end());
+ }
+ return fstab;
+}
+
static bool GetRootEntry(FstabEntry* root_entry) {
Fstab proc_mounts;
if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
@@ -218,14 +224,13 @@
return rollbacked;
}
-// Class Definitions
-// -----------------
-FirstStageMount::FirstStageMount(Fstab fstab) : need_dm_verity_(false), fstab_(std::move(fstab)) {
- super_partition_name_ = fs_mgr_get_super_partition_name();
-}
-
-Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create() {
- auto fstab = ReadFirstStageFstab();
+Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create(const std::string& cmdline) {
+ Result<Fstab> fstab;
+ if (IsMicrodroid()) {
+ fstab = ReadFirstStageFstabMicrodroid(cmdline);
+ } else {
+ fstab = ReadFirstStageFstabAndroid();
+ }
if (!fstab.ok()) {
return fstab.error();
}
@@ -233,7 +238,7 @@
return std::make_unique<FirstStageMountVBootV2>(std::move(*fstab));
}
-bool FirstStageMount::DoCreateDevices() {
+bool FirstStageMountVBootV2::DoCreateDevices() {
if (!InitDevices()) return false;
// Mount /metadata before creating logical partitions, since we need to
@@ -255,7 +260,7 @@
return true;
}
-bool FirstStageMount::DoFirstStageMount() {
+bool FirstStageMountVBootV2::DoFirstStageMount() {
if (!IsDmLinearEnabled() && fstab_.empty()) {
// Nothing to mount.
LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
@@ -267,7 +272,7 @@
return true;
}
-bool FirstStageMount::InitDevices() {
+bool FirstStageMountVBootV2::InitDevices() {
std::set<std::string> devices;
GetSuperDeviceName(&devices);
@@ -288,14 +293,14 @@
return true;
}
-bool FirstStageMount::IsDmLinearEnabled() {
+bool FirstStageMountVBootV2::IsDmLinearEnabled() {
for (const auto& entry : fstab_) {
if (entry.fs_mgr_flags.logical) return true;
}
return false;
}
-void FirstStageMount::GetSuperDeviceName(std::set<std::string>* devices) {
+void FirstStageMountVBootV2::GetSuperDeviceName(std::set<std::string>* devices) {
// Add any additional devices required for dm-linear mappings.
if (!IsDmLinearEnabled()) {
return;
@@ -307,7 +312,7 @@
// Creates devices with uevent->partition_name matching ones in the given set.
// Found partitions will then be removed from it for the subsequent member
// function to check which devices are NOT created.
-bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
+bool FirstStageMountVBootV2::InitRequiredDevices(std::set<std::string> devices) {
if (!block_dev_init_.InitDeviceMapper()) {
return false;
}
@@ -317,7 +322,8 @@
return block_dev_init_.InitDevices(std::move(devices));
}
-bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
+bool FirstStageMountVBootV2::InitDmLinearBackingDevices(
+ const android::fs_mgr::LpMetadata& metadata) {
std::set<std::string> devices;
auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
@@ -334,7 +340,7 @@
return InitRequiredDevices(std::move(devices));
}
-bool FirstStageMount::CreateLogicalPartitions() {
+bool FirstStageMountVBootV2::CreateLogicalPartitions() {
if (!IsDmLinearEnabled()) {
return true;
}
@@ -365,7 +371,7 @@
return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path_);
}
-bool FirstStageMount::CreateSnapshotPartitions(SnapshotManager* sm) {
+bool FirstStageMountVBootV2::CreateSnapshotPartitions(SnapshotManager* sm) {
// When COW images are present for snapshots, they are stored on
// the data partition.
if (!InitRequiredDevices({"userdata"})) {
@@ -400,8 +406,8 @@
return true;
}
-bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
- Fstab::iterator* end) {
+bool FirstStageMountVBootV2::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
+ Fstab::iterator* end) {
// Sets end to begin + 1, so we can just return on failure below.
if (end) {
*end = begin + 1;
@@ -445,7 +451,7 @@
return mounted;
}
-void FirstStageMount::PreloadAvbKeys() {
+void FirstStageMountVBootV2::PreloadAvbKeys() {
for (const auto& entry : fstab_) {
// No need to cache the key content if it's empty, or is already cached.
if (entry.avb_keys.empty() || preload_avb_key_blobs_.count(entry.avb_keys)) {
@@ -492,7 +498,7 @@
// If system is in the fstab then we're not a system-as-root device, and in
// this case, we mount system first then pivot to it. From that point on,
// we are effectively identical to a system-as-root device.
-bool FirstStageMount::TrySwitchSystemAsRoot() {
+bool FirstStageMountVBootV2::TrySwitchSystemAsRoot() {
UseDsuIfPresent();
// Preloading all AVB keys from the ramdisk before switching root to /system.
PreloadAvbKeys();
@@ -521,7 +527,7 @@
return true;
}
-bool FirstStageMount::MountPartitions() {
+bool FirstStageMountVBootV2::MountPartitions() {
if (!TrySwitchSystemAsRoot()) return false;
if (!SkipMountingPartitions(&fstab_, true /* verbose */)) return false;
@@ -604,7 +610,7 @@
// copy files to /metadata is NOT fatal, because it is auxiliary to perform
// public key matching before booting into DSU images on next boot. The actual
// public key matching will still be done on next boot to DSU.
-void FirstStageMount::CopyDsuAvbKeys() {
+void FirstStageMountVBootV2::CopyDsuAvbKeys() {
std::error_code ec;
// Removing existing keys in gsi::kDsuAvbKeyDir as they might be stale.
std::filesystem::remove_all(gsi::kDsuAvbKeyDir, ec);
@@ -620,7 +626,7 @@
}
}
-void FirstStageMount::UseDsuIfPresent() {
+void FirstStageMountVBootV2::UseDsuIfPresent() {
std::string error;
if (!android::gsi::CanBootIntoGsi(&error)) {
@@ -657,10 +663,10 @@
TransformFstabForDsu(&fstab_, active_dsu, dsu_partitions);
}
-// First retrieve any vbmeta partitions from device tree (legacy) then read through the fstab
-// for any further vbmeta partitions.
FirstStageMountVBootV2::FirstStageMountVBootV2(Fstab fstab)
- : FirstStageMount(std::move(fstab)), avb_handle_(nullptr) {
+ : need_dm_verity_(false), fstab_(std::move(fstab)), avb_handle_(nullptr) {
+ super_partition_name_ = fs_mgr_get_super_partition_name();
+
std::string device_tree_vbmeta_parts;
read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts);
@@ -793,46 +799,13 @@
return true;
}
-// Public functions
-// ----------------
-// Creates devices and logical partitions from storage devices
-bool DoCreateDevices() {
- auto fsm = FirstStageMount::Create();
- if (!fsm.ok()) {
- LOG(ERROR) << "Failed to create FirstStageMount: " << fsm.error();
- return false;
- }
- return (*fsm)->DoCreateDevices();
-}
-
-// Mounts partitions specified by fstab in device tree.
-bool DoFirstStageMount(bool create_devices) {
- // Skips first stage mount if we're in recovery mode.
- if (IsRecoveryMode()) {
- LOG(INFO) << "First stage mount skipped (recovery mode)";
- return true;
- }
-
- auto fsm = FirstStageMount::Create();
- if (!fsm.ok()) {
- LOG(ERROR) << "Failed to create FirstStageMount " << fsm.error();
- return false;
- }
-
- if (create_devices) {
- if (!(*fsm)->DoCreateDevices()) return false;
- }
-
- return (*fsm)->DoFirstStageMount();
-}
-
void SetInitAvbVersionInRecovery() {
if (!IsRecoveryMode()) {
LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
return;
}
- auto fstab = ReadFirstStageFstab();
+ auto fstab = ReadFirstStageFstabAndroid();
if (!fstab.ok()) {
LOG(ERROR) << fstab.error();
return;
diff --git a/init/first_stage_mount.h b/init/first_stage_mount.h
index 2f4e663..54501d8 100644
--- a/init/first_stage_mount.h
+++ b/init/first_stage_mount.h
@@ -16,11 +16,28 @@
#pragma once
+#include <memory>
+
+#include "result.h"
+
namespace android {
namespace init {
-bool DoCreateDevices();
-bool DoFirstStageMount(bool create_devices);
+class FirstStageMount {
+ public:
+ virtual ~FirstStageMount() = default;
+
+ // The factory method to create a FirstStageMount instance.
+ static Result<std::unique_ptr<FirstStageMount>> Create(const std::string& cmdline);
+ // Creates devices and logical partitions from storage devices
+ virtual bool DoCreateDevices() = 0;
+ // Mounts fstab entries read from device tree.
+ virtual bool DoFirstStageMount() = 0;
+
+ protected:
+ FirstStageMount() = default;
+};
+
void SetInitAvbVersionInRecovery();
} // namespace init
diff --git a/init/fuzzer/Android.bp b/init/fuzzer/Android.bp
index c21a196..856ca8c 100644
--- a/init/fuzzer/Android.bp
+++ b/init/fuzzer/Android.bp
@@ -18,7 +18,7 @@
}
cc_defaults {
- name: "libinit_defaults",
+ name: "libinit_fuzzer_defaults",
static_libs: [
"libc++fs",
"liblmkd_utils",
@@ -53,7 +53,7 @@
],
shared_libs: ["libhidlmetadata",],
defaults: [
- "libinit_defaults",
+ "libinit_fuzzer_defaults",
],
}
@@ -62,7 +62,7 @@
srcs: [
"init_property_fuzzer.cpp",
],
- defaults: ["libinit_defaults"],
+ defaults: ["libinit_fuzzer_defaults"],
}
cc_fuzz {
@@ -71,6 +71,6 @@
"init_ueventHandler_fuzzer.cpp",
],
defaults: [
- "libinit_defaults",
+ "libinit_fuzzer_defaults",
],
}
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index fead371..5b53d50 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -21,7 +21,6 @@
#include <string>
#include <vector>
-#include <ApexProperties.sysprop.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -30,16 +29,6 @@
#include "util.h"
-#ifndef RECOVERY
-#define ACTIVATE_FLATTENED_APEX 1
-#endif
-
-#ifdef ACTIVATE_FLATTENED_APEX
-#include <apex_manifest.pb.h>
-#include <com_android_apex.h>
-#include <selinux/android.h>
-#endif // ACTIVATE_FLATTENED_APEX
-
namespace android {
namespace init {
namespace {
@@ -77,15 +66,9 @@
return ret;
}
-static bool IsApexUpdatable() {
- static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
- return updatable;
-}
-
// In case we have two sets of APEXes (non-updatable, updatable), we need two separate mount
// namespaces.
static bool NeedsTwoMountNamespaces() {
- if (!IsApexUpdatable()) return false;
if (IsRecoveryMode()) return false;
// In microdroid, there's only one set of APEXes in built-in directories include block devices.
if (IsMicrodroid()) return false;
@@ -193,7 +176,7 @@
// Switch the mount namespace of the current process from bootstrap to default OR from default to
// bootstrap. If the current mount namespace is neither bootstrap nor default, keep it that way.
Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace) {
- if (IsRecoveryMode() || !IsApexUpdatable()) {
+ if (IsRecoveryMode()) {
// we don't have multiple namespaces in recovery mode or if apex is not updatable
return {};
}
diff --git a/init/selinux.cpp b/init/selinux.cpp
index a936532..b6d483a 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -74,10 +74,8 @@
#include <android-base/unique_fd.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr.h>
-#include <fsverity_init.h>
#include <libgsi/libgsi.h>
#include <libsnapshot/snapshot.h>
-#include <mini_keyctl_utils.h>
#include <selinux/android.h>
#include <ziparchive/zip_archive.h>
@@ -300,8 +298,6 @@
}
constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
-constexpr const char kMicrodroidPrecompiledSepolicy[] =
- "/system/etc/selinux/microdroid_precompiled_sepolicy";
bool IsSplitPolicyDevice() {
return access(plat_policy_cil_file, R_OK) != -1;
@@ -499,25 +495,19 @@
bool OpenMonolithicPolicy(PolicyFile* policy_file) {
static constexpr char kSepolicyFile[] = "/sepolicy";
- // In Microdroid the precompiled sepolicy is located on /system, since there is no vendor code.
- // TODO(b/287206497): refactor once we start conditionally compiling init for Microdroid.
- std::string monolithic_policy_file = access(kMicrodroidPrecompiledSepolicy, R_OK) == 0
- ? kMicrodroidPrecompiledSepolicy
- : kSepolicyFile;
- LOG(INFO) << "Opening SELinux policy from monolithic file " << monolithic_policy_file;
- policy_file->fd.reset(open(monolithic_policy_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ LOG(INFO) << "Opening SELinux policy from monolithic file " << kSepolicyFile;
+ policy_file->fd.reset(open(kSepolicyFile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (policy_file->fd < 0) {
PLOG(ERROR) << "Failed to open monolithic SELinux policy";
return false;
}
- policy_file->path = monolithic_policy_file;
+ policy_file->path = kSepolicyFile;
return true;
}
constexpr const char* kSigningCertRelease =
"/system/etc/selinux/com.android.sepolicy.cert-release.der";
-constexpr const char* kFsVerityProcPath = "/proc/sys/fs/verity";
const std::string kSepolicyApexMetadataDir = "/metadata/sepolicy/";
const std::string kSepolicyApexSystemDir = "/system/etc/selinux/apex/";
const std::string kSepolicyZip = "SEPolicy.zip";
@@ -621,24 +611,6 @@
return {};
}
-Result<void> LoadSepolicyApexCerts() {
- key_serial_t keyring_id = android::GetKeyringId(".fs-verity");
- if (keyring_id < 0) {
- return Error() << "Failed to find .fs-verity keyring id";
- }
-
- // TODO(b/199914227) the release key should always exist. Once it's checked in, start
- // throwing an error here if it doesn't exist.
- if (access(kSigningCertRelease, F_OK) == 0) {
- LoadKeyFromFile(keyring_id, "fsv_sepolicy_apex_release", kSigningCertRelease);
- }
- return {};
-}
-
-Result<void> SepolicyFsVerityCheck() {
- return Error() << "TODO implement support for fsverity SEPolicy.";
-}
-
Result<void> SepolicyCheckSignature(const std::string& dir) {
std::string signature;
if (!android::base::ReadFileToString(dir + kSepolicySignature, &signature)) {
@@ -661,18 +633,7 @@
return verifySignature(sepolicyStr, signature, *releaseKey);
}
-Result<void> SepolicyVerify(const std::string& dir, bool supportsFsVerity) {
- if (supportsFsVerity) {
- auto fsVerityCheck = SepolicyFsVerityCheck();
- if (fsVerityCheck.ok()) {
- return fsVerityCheck;
- }
- // TODO(b/199914227) If the device supports fsverity, but we fail here, we should fail to
- // boot and not carry on. For now, fallback to a signature checkuntil the fsverity
- // logic is implemented.
- LOG(INFO) << "Falling back to standard signature check. " << fsVerityCheck.error();
- }
-
+Result<void> SepolicyVerify(const std::string& dir) {
auto sepolicySignature = SepolicyCheckSignature(dir);
if (!sepolicySignature.ok()) {
return Error() << "Apex SEPolicy failed signature check";
@@ -705,23 +666,13 @@
// 6. Sets selinux into enforcing mode and continues normal booting.
//
void PrepareApexSepolicy() {
- bool supportsFsVerity = access(kFsVerityProcPath, F_OK) == 0;
- if (supportsFsVerity) {
- auto loadSepolicyApexCerts = LoadSepolicyApexCerts();
- if (!loadSepolicyApexCerts.ok()) {
- // TODO(b/199914227) If the device supports fsverity, but we fail here, we should fail
- // to boot and not carry on. For now, fallback to a signature checkuntil the fsverity
- // logic is implemented.
- LOG(INFO) << loadSepolicyApexCerts.error();
- }
- }
// If apex sepolicy zip exists in /metadata/sepolicy, use that, otherwise use version on
// /system.
auto dir = (access((kSepolicyApexMetadataDir + kSepolicyZip).c_str(), F_OK) == 0)
? kSepolicyApexMetadataDir
: kSepolicyApexSystemDir;
- auto sepolicyVerify = SepolicyVerify(dir, supportsFsVerity);
+ auto sepolicyVerify = SepolicyVerify(dir);
if (!sepolicyVerify.ok()) {
LOG(INFO) << "Error: " << sepolicyVerify.error();
// If signature verification fails, fall back to version on /system.
@@ -858,6 +809,10 @@
}
int SelinuxGetVendorAndroidVersion() {
+ if (IsMicrodroid()) {
+ // As of now Microdroid doesn't have any vendor code.
+ return __ANDROID_API_FUTURE__;
+ }
static int vendor_android_version = [] {
if (!IsSplitPolicyDevice()) {
// If this device does not split sepolicy files, it's not a Treble device and therefore,
@@ -961,6 +916,26 @@
}
}
+// Encapsulates steps to load SELinux policy in Microdroid.
+// So far the process is very straightforward - just load the precompiled policy from /system.
+void LoadSelinuxPolicyMicrodroid() {
+ constexpr const char kMicrodroidPrecompiledSepolicy[] =
+ "/system/etc/selinux/microdroid_precompiled_sepolicy";
+
+ LOG(INFO) << "Opening SELinux policy from " << kMicrodroidPrecompiledSepolicy;
+ unique_fd policy_fd(open(kMicrodroidPrecompiledSepolicy, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ if (policy_fd < 0) {
+ PLOG(FATAL) << "Failed to open " << kMicrodroidPrecompiledSepolicy;
+ }
+
+ std::string policy;
+ if (!android::base::ReadFdToString(policy_fd, &policy)) {
+ PLOG(FATAL) << "Failed to read policy file: " << kMicrodroidPrecompiledSepolicy;
+ }
+
+ LoadSelinuxPolicy(policy);
+}
+
// The SELinux setup process is carefully orchestrated around snapuserd. Policy
// must be loaded off dynamic partitions, and during an OTA, those partitions
// cannot be read without snapuserd. But, with kernel-privileged snapuserd
@@ -976,20 +951,9 @@
// (5) Re-launch snapuserd and attach it to the dm-user devices from step (2).
//
// After this sequence, it is safe to enable enforcing mode and continue booting.
-int SetupSelinux(char** argv) {
- SetStdioToDevNull(argv);
- InitKernelLogging(argv);
-
- if (REBOOT_BOOTLOADER_ON_PANIC) {
- InstallRebootSignalHandlers();
- }
-
- boot_clock::time_point start_time = boot_clock::now();
-
+void LoadSelinuxPolicyAndroid() {
MountMissingSystemPartitions();
- SelinuxSetupKernelLogging();
-
LOG(INFO) << "Opening SELinux policy";
PrepareApexSepolicy();
@@ -1001,9 +965,8 @@
auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
if (snapuserd_helper) {
- // Kill the old snapused to avoid audit messages. After this we cannot
- // read from /system (or other dynamic partitions) until we call
- // FinishTransition().
+ // Kill the old snapused to avoid audit messages. After this we cannot read from /system
+ // (or other dynamic partitions) until we call FinishTransition().
snapuserd_helper->StartTransition();
}
@@ -1021,6 +984,26 @@
if (selinux_android_restorecon("/dev/selinux/", SELINUX_ANDROID_RESTORECON_RECURSE) == -1) {
PLOG(FATAL) << "restorecon failed of /dev/selinux failed";
}
+}
+
+int SetupSelinux(char** argv) {
+ SetStdioToDevNull(argv);
+ InitKernelLogging(argv);
+
+ if (REBOOT_BOOTLOADER_ON_PANIC) {
+ InstallRebootSignalHandlers();
+ }
+
+ boot_clock::time_point start_time = boot_clock::now();
+
+ SelinuxSetupKernelLogging();
+
+ // TODO(b/287206497): refactor into different headers to only include what we need.
+ if (IsMicrodroid()) {
+ LoadSelinuxPolicyMicrodroid();
+ } else {
+ LoadSelinuxPolicyAndroid();
+ }
SelinuxSetEnforcement();
diff --git a/init/service.cpp b/init/service.cpp
index 2945708..a0b3478 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -50,7 +50,6 @@
#endif
#ifdef INIT_FULL_SOURCES
-#include <ApexProperties.sysprop.h>
#include <android/api-level.h>
#include "mount_namespace.h"
@@ -323,7 +322,7 @@
}
#if INIT_FULL_SOURCES
- static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+ static bool is_apex_updatable = true;
#else
static bool is_apex_updatable = false;
#endif
diff --git a/init/util.cpp b/init/util.cpp
index bc8ea6e..d0478e8 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -732,11 +732,6 @@
is_default_mount_namespace_ready = true;
}
-bool IsMicrodroid() {
- static bool is_microdroid = android::base::GetProperty("ro.hardware", "") == "microdroid";
- return is_microdroid;
-}
-
bool Has32BitAbi() {
static bool has = !android::base::GetProperty("ro.product.cpu.abilist32", "").empty();
return has;
diff --git a/init/util.h b/init/util.h
index e58e70e..3f0a4e0 100644
--- a/init/util.h
+++ b/init/util.h
@@ -105,7 +105,14 @@
bool IsDefaultMountNamespaceReady();
void SetDefaultMountNamespaceReady();
-bool IsMicrodroid();
+inline constexpr bool IsMicrodroid() {
+#ifdef MICRODROID
+ return MICRODROID;
+#else
+ return false;
+#endif
+}
+
bool Has32BitAbi();
std::string GetApexNameFromFileName(const std::string& path);
diff --git a/libbinderwrapper/Android.bp b/libbinderwrapper/Android.bp
deleted file mode 100644
index 75f43ee..0000000
--- a/libbinderwrapper/Android.bp
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Copyright (C) 2015 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.
-//
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_defaults {
- name: "libbinderwrapper_defaults",
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
-
- // for libchrome
- "-Wno-sign-promo",
- ],
- export_include_dirs: ["include"],
- shared_libs: [
- "libbinder",
- "libchrome",
- "libutils",
- ],
-}
-
-// libbinderwrapper shared library
-// ========================================================
-cc_library_shared {
- name: "libbinderwrapper",
- defaults: ["libbinderwrapper_defaults"],
- vendor_available: true,
-
- srcs: [
- "binder_wrapper.cc",
- "real_binder_wrapper.cc",
- ],
-}
-
-// libbinderwrapper_test_support static library
-// ========================================================
-cc_library_static {
- name: "libbinderwrapper_test_support",
- defaults: ["libbinderwrapper_defaults"],
-
- static_libs: ["libgtest"],
- shared_libs: ["libbinderwrapper"],
-
- srcs: [
- "binder_test_base.cc",
- "stub_binder_wrapper.cc",
- ],
-}
diff --git a/libbinderwrapper/binder_test_base.cc b/libbinderwrapper/binder_test_base.cc
deleted file mode 100644
index af93a04..0000000
--- a/libbinderwrapper/binder_test_base.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include <binderwrapper/binder_test_base.h>
-
-#include <binderwrapper/binder_wrapper.h>
-#include <binderwrapper/stub_binder_wrapper.h>
-
-namespace android {
-
-BinderTestBase::BinderTestBase() : binder_wrapper_(new StubBinderWrapper()) {
- // Pass ownership.
- BinderWrapper::InitForTesting(binder_wrapper_);
-}
-
-BinderTestBase::~BinderTestBase() {
- BinderWrapper::Destroy();
-}
-
-} // namespace android
diff --git a/libbinderwrapper/binder_wrapper.cc b/libbinderwrapper/binder_wrapper.cc
deleted file mode 100644
index ca9c1df..0000000
--- a/libbinderwrapper/binder_wrapper.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include <binderwrapper/binder_wrapper.h>
-
-#include <base/logging.h>
-
-#include "real_binder_wrapper.h"
-
-namespace android {
-
-// Singleton instance.
-BinderWrapper* BinderWrapper::instance_ = nullptr;
-
-// static
-void BinderWrapper::Create() {
- CHECK(!instance_) << "Already initialized; missing call to Destroy()?";
- instance_ = new RealBinderWrapper();
-}
-
-// static
-void BinderWrapper::InitForTesting(BinderWrapper* wrapper) {
- CHECK(!instance_) << "Already initialized; missing call to Destroy()?";
- instance_ = wrapper;
-}
-
-// static
-void BinderWrapper::Destroy() {
- CHECK(instance_) << "Not initialized; missing call to Create()?";
- delete instance_;
- instance_ = nullptr;
-}
-
-// static
-BinderWrapper* BinderWrapper::Get() {
- CHECK(instance_) << "Not initialized; missing call to Create()?";
- return instance_;
-}
-
-// static
-BinderWrapper* BinderWrapper::GetOrCreateInstance() {
- if (!instance_)
- instance_ = new RealBinderWrapper();
- return instance_;
-}
-
-} // namespace android
diff --git a/libbinderwrapper/include/binderwrapper/binder_test_base.h b/libbinderwrapper/include/binderwrapper/binder_test_base.h
deleted file mode 100644
index 06543de..0000000
--- a/libbinderwrapper/include/binderwrapper/binder_test_base.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_TEST_BASE_H_
-#define SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_TEST_BASE_H_
-
-#include <base/macros.h>
-#include <gtest/gtest.h>
-
-namespace android {
-
-class StubBinderWrapper;
-
-// Class that can be inherited from (or aliased via typedef/using) when writing
-// tests that use StubBinderManager.
-class BinderTestBase : public ::testing::Test {
- public:
- BinderTestBase();
- ~BinderTestBase() override;
-
- StubBinderWrapper* binder_wrapper() { return binder_wrapper_; }
-
- protected:
- StubBinderWrapper* binder_wrapper_; // Not owned.
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BinderTestBase);
-};
-
-} // namespace android
-
-#endif // SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_TEST_BASE_H_
diff --git a/libbinderwrapper/include/binderwrapper/binder_wrapper.h b/libbinderwrapper/include/binderwrapper/binder_wrapper.h
deleted file mode 100644
index a104bff..0000000
--- a/libbinderwrapper/include/binderwrapper/binder_wrapper.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
-#define SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
-
-#include <sys/types.h>
-
-#include <string>
-
-#include <base/callback.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-class BBinder;
-class IBinder;
-
-// Wraps libbinder to make it testable.
-// NOTE: Static methods of this class are not thread-safe.
-class BinderWrapper {
- public:
- virtual ~BinderWrapper() {}
-
- // Creates and initializes the singleton (using a wrapper that communicates
- // with the real binder system).
- static void Create();
-
- // Initializes |wrapper| as the singleton, taking ownership of it. Tests that
- // want to inject their own wrappers should call this instead of Create().
- static void InitForTesting(BinderWrapper* wrapper);
-
- // Destroys the singleton. Must be called before calling Create() or
- // InitForTesting() a second time.
- static void Destroy();
-
- // Returns the singleton instance previously created by Create() or set by
- // InitForTesting().
- static BinderWrapper* Get();
-
- // Returns the singleton instance if it was previously created by Create() or
- // set by InitForTesting(), or creates a new one by calling Create().
- static BinderWrapper* GetOrCreateInstance();
-
- // Gets the binder for communicating with the service identified by
- // |service_name|, returning null immediately if it doesn't exist.
- virtual sp<IBinder> GetService(const std::string& service_name) = 0;
-
- // Registers |binder| as |service_name| with the service manager.
- virtual bool RegisterService(const std::string& service_name,
- const sp<IBinder>& binder) = 0;
-
- // Creates a local binder object.
- virtual sp<BBinder> CreateLocalBinder() = 0;
-
- // Registers |callback| to be invoked when |binder| dies. If another callback
- // is currently registered for |binder|, it will be replaced.
- virtual bool RegisterForDeathNotifications(
- const sp<IBinder>& binder,
- const ::base::Closure& callback) = 0;
-
- // Unregisters the callback, if any, for |binder|.
- virtual bool UnregisterForDeathNotifications(const sp<IBinder>& binder) = 0;
-
- // When called while in a transaction, returns the caller's UID or PID.
- virtual uid_t GetCallingUid() = 0;
- virtual pid_t GetCallingPid() = 0;
-
- private:
- static BinderWrapper* instance_;
-};
-
-} // namespace android
-
-#endif // SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
diff --git a/libbinderwrapper/include/binderwrapper/stub_binder_wrapper.h b/libbinderwrapper/include/binderwrapper/stub_binder_wrapper.h
deleted file mode 100644
index 9d4578e..0000000
--- a/libbinderwrapper/include/binderwrapper/stub_binder_wrapper.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef SYSTEM_CORE_INCLUDE_BINDERWRAPPER_STUB_BINDER_WRAPPER_H_
-#define SYSTEM_CORE_INCLUDE_BINDERWRAPPER_STUB_BINDER_WRAPPER_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binderwrapper/binder_wrapper.h>
-
-namespace android {
-
-// Stub implementation of BinderWrapper for testing.
-//
-// Example usage:
-//
-// First, assuming a base IFoo binder interface, create a stub class that
-// derives from BnFoo to implement the receiver side of the communication:
-//
-// class StubFoo : public BnFoo {
-// public:
-// ...
-// status_t doSomething(int arg) override {
-// // e.g. save passed-in value for later inspection by tests.
-// return OK;
-// }
-// };
-//
-// Next, from your test code, inject a StubBinderManager either directly or by
-// inheriting from the BinderTestBase class:
-//
-// StubBinderWrapper* wrapper = new StubBinderWrapper();
-// BinderWrapper::InitForTesting(wrapper); // Takes ownership.
-//
-// Also from your test, create a StubFoo and register it with the wrapper:
-//
-// StubFoo* foo = new StubFoo();
-// sp<IBinder> binder(foo);
-// wrapper->SetBinderForService("foo", binder);
-//
-// The code being tested can now use the wrapper to get the stub and call it:
-//
-// sp<IBinder> binder = BinderWrapper::Get()->GetService("foo");
-// CHECK(binder.get());
-// sp<IFoo> foo = interface_cast<IFoo>(binder);
-// CHECK_EQ(foo->doSomething(3), OK);
-//
-// To create a local BBinder object, production code can call
-// CreateLocalBinder(). Then, a test can get the BBinder's address via
-// local_binders() to check that they're passed as expected in binder calls.
-//
-class StubBinderWrapper : public BinderWrapper {
- public:
- StubBinderWrapper();
- ~StubBinderWrapper() override;
-
- const std::vector<sp<BBinder>>& local_binders() const {
- return local_binders_;
- }
- void clear_local_binders() { local_binders_.clear(); }
-
- void set_calling_uid(uid_t uid) { calling_uid_ = uid; }
- void set_calling_pid(pid_t pid) { calling_pid_ = pid; }
-
- // Sets the binder to return when |service_name| is passed to GetService() or
- // WaitForService().
- void SetBinderForService(const std::string& service_name,
- const sp<IBinder>& binder);
-
- // Returns the binder previously registered for |service_name| via
- // RegisterService(), or null if the service hasn't been registered.
- sp<IBinder> GetRegisteredService(const std::string& service_name) const;
-
- // Run the calback in |death_callbacks_| corresponding to |binder|.
- void NotifyAboutBinderDeath(const sp<IBinder>& binder);
-
- // BinderWrapper:
- sp<IBinder> GetService(const std::string& service_name) override;
- bool RegisterService(const std::string& service_name,
- const sp<IBinder>& binder) override;
- sp<BBinder> CreateLocalBinder() override;
- bool RegisterForDeathNotifications(const sp<IBinder>& binder,
- const ::base::Closure& callback) override;
- bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
- uid_t GetCallingUid() override;
- pid_t GetCallingPid() override;
-
- private:
- using ServiceMap = std::map<std::string, sp<IBinder>>;
-
- // Map from service name to associated binder handle. Used by GetService() and
- // WaitForService().
- ServiceMap services_to_return_;
-
- // Map from service name to associated binder handle. Updated by
- // RegisterService().
- ServiceMap registered_services_;
-
- // Local binders returned by CreateLocalBinder().
- std::vector<sp<BBinder>> local_binders_;
-
- // Map from binder handle to the callback that should be invoked on binder
- // death.
- std::map<sp<IBinder>, ::base::Closure> death_callbacks_;
-
- // Values to return from GetCallingUid() and GetCallingPid();
- uid_t calling_uid_;
- pid_t calling_pid_;
-
- DISALLOW_COPY_AND_ASSIGN(StubBinderWrapper);
-};
-
-} // namespace android
-
-#endif // SYSTEM_CORE_INCLUDE_BINDERWRAPPER_STUB_BINDER_WRAPPER_H_
diff --git a/libbinderwrapper/real_binder_wrapper.cc b/libbinderwrapper/real_binder_wrapper.cc
deleted file mode 100644
index f93f183..0000000
--- a/libbinderwrapper/real_binder_wrapper.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include "real_binder_wrapper.h"
-
-#include <base/logging.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-namespace android {
-
-// Class that handles binder death notifications. libbinder wants the recipient
-// to be wrapped in sp<>, so registering RealBinderWrapper as a recipient would
-// be awkward.
-class RealBinderWrapper::DeathRecipient : public IBinder::DeathRecipient {
- public:
- explicit DeathRecipient(const ::base::Closure& callback)
- : callback_(callback) {}
- ~DeathRecipient() = default;
-
- // IBinder::DeathRecipient:
- void binderDied(const wp<IBinder>& who) override {
- callback_.Run();
- }
-
- private:
- // Callback to run in response to binder death.
- ::base::Closure callback_;
-
- DISALLOW_COPY_AND_ASSIGN(DeathRecipient);
-};
-
-RealBinderWrapper::RealBinderWrapper() = default;
-
-RealBinderWrapper::~RealBinderWrapper() = default;
-
-sp<IBinder> RealBinderWrapper::GetService(const std::string& service_name) {
- sp<IServiceManager> service_manager = defaultServiceManager();
- if (!service_manager.get()) {
- LOG(ERROR) << "Unable to get service manager";
- return sp<IBinder>();
- }
- sp<IBinder> binder =
- service_manager->checkService(String16(service_name.c_str()));
- if (!binder.get())
- LOG(ERROR) << "Unable to get \"" << service_name << "\" service";
- return binder;
-}
-
-bool RealBinderWrapper::RegisterService(const std::string& service_name,
- const sp<IBinder>& binder) {
- sp<IServiceManager> service_manager = defaultServiceManager();
- if (!service_manager.get()) {
- LOG(ERROR) << "Unable to get service manager";
- return false;
- }
- status_t status = defaultServiceManager()->addService(
- String16(service_name.c_str()), binder);
- if (status != OK) {
- LOG(ERROR) << "Failed to register \"" << service_name << "\" with service "
- << "manager";
- return false;
- }
- return true;
-}
-
-sp<BBinder> RealBinderWrapper::CreateLocalBinder() {
- return sp<BBinder>(new BBinder());
-}
-
-bool RealBinderWrapper::RegisterForDeathNotifications(
- const sp<IBinder>& binder,
- const ::base::Closure& callback) {
- sp<DeathRecipient> recipient(new DeathRecipient(callback));
- if (binder->linkToDeath(recipient) != OK) {
- LOG(ERROR) << "Failed to register for death notifications on "
- << binder.get();
- return false;
- }
- death_recipients_[binder] = recipient;
- return true;
-}
-
-bool RealBinderWrapper::UnregisterForDeathNotifications(
- const sp<IBinder>& binder) {
- auto it = death_recipients_.find(binder);
- if (it == death_recipients_.end()) {
- LOG(ERROR) << "Not registered for death notifications on " << binder.get();
- return false;
- }
- if (binder->unlinkToDeath(it->second) != OK) {
- LOG(ERROR) << "Failed to unregister for death notifications on "
- << binder.get();
- return false;
- }
- death_recipients_.erase(it);
- return true;
-}
-
-uid_t RealBinderWrapper::GetCallingUid() {
- return IPCThreadState::self()->getCallingUid();
-}
-
-pid_t RealBinderWrapper::GetCallingPid() {
- return IPCThreadState::self()->getCallingPid();
-}
-
-} // namespace android
diff --git a/libbinderwrapper/real_binder_wrapper.h b/libbinderwrapper/real_binder_wrapper.h
deleted file mode 100644
index fa05383..0000000
--- a/libbinderwrapper/real_binder_wrapper.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef SYSTEM_CORE_LIBBINDERWRAPPER_REAL_BINDER_WRAPPER_H_
-#define SYSTEM_CORE_LIBBINDERWRAPPER_REAL_BINDER_WRAPPER_H_
-
-#include <map>
-
-#include <base/macros.h>
-#include <binderwrapper/binder_wrapper.h>
-
-namespace android {
-
-class IBinder;
-
-// Real implementation of BinderWrapper.
-class RealBinderWrapper : public BinderWrapper {
- public:
- RealBinderWrapper();
- ~RealBinderWrapper() override;
-
- // BinderWrapper:
- sp<IBinder> GetService(const std::string& service_name) override;
- bool RegisterService(const std::string& service_name,
- const sp<IBinder>& binder) override;
- sp<BBinder> CreateLocalBinder() override;
- bool RegisterForDeathNotifications(const sp<IBinder>& binder,
- const ::base::Closure& callback) override;
- bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
- uid_t GetCallingUid() override;
- pid_t GetCallingPid() override;
-
- private:
- class DeathRecipient;
-
- // Map from binder handle to object that should be notified of the binder's
- // death.
- std::map<sp<IBinder>, sp<DeathRecipient>> death_recipients_;
-
- DISALLOW_COPY_AND_ASSIGN(RealBinderWrapper);
-};
-
-} // namespace android
-
-#endif // SYSTEM_CORE_LIBBINDER_WRAPPER_REAL_BINDER_WRAPPER_H_
diff --git a/libbinderwrapper/stub_binder_wrapper.cc b/libbinderwrapper/stub_binder_wrapper.cc
deleted file mode 100644
index 8e75f62..0000000
--- a/libbinderwrapper/stub_binder_wrapper.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#include <binderwrapper/stub_binder_wrapper.h>
-
-#include <base/logging.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-
-namespace android {
-
-StubBinderWrapper::StubBinderWrapper()
- : calling_uid_(-1),
- calling_pid_(-1) {}
-
-StubBinderWrapper::~StubBinderWrapper() = default;
-
-void StubBinderWrapper::SetBinderForService(const std::string& service_name,
- const sp<IBinder>& binder) {
- services_to_return_[service_name] = binder;
-}
-
-sp<IBinder> StubBinderWrapper::GetRegisteredService(
- const std::string& service_name) const {
- const auto it = registered_services_.find(service_name);
- return it != registered_services_.end() ? it->second : sp<IBinder>();
-}
-
-void StubBinderWrapper::NotifyAboutBinderDeath(const sp<IBinder>& binder) {
- const auto it = death_callbacks_.find(binder);
- if (it != death_callbacks_.end())
- it->second.Run();
-}
-
-sp<IBinder> StubBinderWrapper::GetService(const std::string& service_name) {
- const auto it = services_to_return_.find(service_name);
- return it != services_to_return_.end() ? it->second : sp<IBinder>();
-}
-
-bool StubBinderWrapper::RegisterService(const std::string& service_name,
- const sp<IBinder>& binder) {
- registered_services_[service_name] = binder;
- return true;
-}
-
-sp<BBinder> StubBinderWrapper::CreateLocalBinder() {
- sp<BBinder> binder(new BBinder());
- local_binders_.push_back(binder);
- return binder;
-}
-
-bool StubBinderWrapper::RegisterForDeathNotifications(
- const sp<IBinder>& binder,
- const ::base::Closure& callback) {
- death_callbacks_[binder] = callback;
- return true;
-}
-
-bool StubBinderWrapper::UnregisterForDeathNotifications(
- const sp<IBinder>& binder) {
- death_callbacks_.erase(binder);
- return true;
-}
-
-uid_t StubBinderWrapper::GetCallingUid() {
- return calling_uid_;
-}
-
-pid_t StubBinderWrapper::GetCallingPid() {
- return calling_pid_;
-}
-
-} // namespace android
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 0b5c125..92486e3 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -219,11 +219,19 @@
exclude_srcs: [
"qtaguid.cpp",
],
+ header_abi_checker: {
+ enabled: true,
+ ref_dump_dirs: ["abi-dumps"],
+ },
},
product: {
exclude_srcs: [
"qtaguid.cpp",
],
+ header_abi_checker: {
+ enabled: true,
+ ref_dump_dirs: ["abi-dumps"],
+ },
},
},
diff --git a/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump b/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
new file mode 100644
index 0000000..333e61c
--- /dev/null
+++ b/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
@@ -0,0 +1,2690 @@
+{
+ "array_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIA0_i",
+ "name" : "int[0]",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIA0_i",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ }
+ ],
+ "builtin_types" :
+ [
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIa",
+ "name" : "signed char",
+ "referenced_type" : "_ZTIa",
+ "self_type" : "_ZTIa",
+ "size" : 1
+ },
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIb",
+ "name" : "bool",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIb",
+ "size" : 1
+ },
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIc",
+ "name" : "char",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIc",
+ "size" : 1
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIf",
+ "name" : "float",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIf",
+ "size" : 4
+ },
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIi",
+ "name" : "int",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIi",
+ "size" : 4
+ },
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIj",
+ "name" : "unsigned int",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIj",
+ "size" : 4
+ },
+ {
+ "alignment" : 8,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIl",
+ "name" : "long",
+ "referenced_type" : "_ZTIl",
+ "self_type" : "_ZTIl",
+ "size" : 8
+ },
+ {
+ "alignment" : 8,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIm",
+ "name" : "unsigned long",
+ "referenced_type" : "_ZTIm",
+ "self_type" : "_ZTIm",
+ "size" : 8
+ },
+ {
+ "linker_set_key" : "_ZTIv",
+ "name" : "void",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIv"
+ }
+ ],
+ "elf_functions" :
+ [
+ {
+ "name" : "_Z23socket_make_sockaddr_unPKciP11sockaddr_unPj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZN7android4base4TrimIRNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEES8_OT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4syncEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE5imbueERKNS_6localeE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE6setbufEPcl"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE7seekoffExNS_8ios_base7seekdirEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE7seekposENS_4fposI9mbstate_tEEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE8overflowEi"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE9pbackfailEi"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE9underflowEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEEC2Ev"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED0Ev"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED2Ev"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__16vectorI5EntryNS_9allocatorIS1_EEE24__emplace_back_slow_pathIJS1_EEEvDpOT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__17getlineIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS_13basic_istreamIT_T0_EES9_RNS_12basic_stringIS6_S7_T1_EES6_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc"
+ },
+ {
+ "name" : "android_get_control_file"
+ },
+ {
+ "name" : "android_get_control_socket"
+ },
+ {
+ "name" : "android_get_ioprio"
+ },
+ {
+ "name" : "android_reboot"
+ },
+ {
+ "name" : "android_set_ioprio"
+ },
+ {
+ "name" : "ashmem_create_region"
+ },
+ {
+ "name" : "ashmem_get_size_region"
+ },
+ {
+ "name" : "ashmem_pin_region"
+ },
+ {
+ "name" : "ashmem_set_prot_region"
+ },
+ {
+ "name" : "ashmem_unpin_region"
+ },
+ {
+ "name" : "ashmem_valid"
+ },
+ {
+ "name" : "atrace_async_begin_body"
+ },
+ {
+ "name" : "atrace_async_end_body"
+ },
+ {
+ "name" : "atrace_async_for_track_begin_body"
+ },
+ {
+ "name" : "atrace_async_for_track_end_body"
+ },
+ {
+ "name" : "atrace_begin_body"
+ },
+ {
+ "name" : "atrace_end_body"
+ },
+ {
+ "name" : "atrace_get_enabled_tags"
+ },
+ {
+ "name" : "atrace_init"
+ },
+ {
+ "name" : "atrace_instant_body"
+ },
+ {
+ "name" : "atrace_instant_for_track_body"
+ },
+ {
+ "name" : "atrace_int64_body"
+ },
+ {
+ "name" : "atrace_int_body"
+ },
+ {
+ "name" : "atrace_set_tracing_enabled"
+ },
+ {
+ "name" : "atrace_setup"
+ },
+ {
+ "name" : "atrace_update_tags"
+ },
+ {
+ "name" : "canned_fs_config"
+ },
+ {
+ "name" : "config_bool"
+ },
+ {
+ "name" : "config_find"
+ },
+ {
+ "name" : "config_free"
+ },
+ {
+ "name" : "config_load"
+ },
+ {
+ "name" : "config_load_file"
+ },
+ {
+ "name" : "config_node"
+ },
+ {
+ "name" : "config_set"
+ },
+ {
+ "name" : "config_str"
+ },
+ {
+ "name" : "fs_config"
+ },
+ {
+ "name" : "fs_mkdirs"
+ },
+ {
+ "name" : "fs_prepare_dir"
+ },
+ {
+ "name" : "fs_prepare_dir_strict"
+ },
+ {
+ "name" : "fs_prepare_file_strict"
+ },
+ {
+ "name" : "fs_read_atomic_int"
+ },
+ {
+ "name" : "fs_write_atomic_int"
+ },
+ {
+ "name" : "hashmapCreate"
+ },
+ {
+ "name" : "hashmapForEach"
+ },
+ {
+ "name" : "hashmapFree"
+ },
+ {
+ "name" : "hashmapGet"
+ },
+ {
+ "name" : "hashmapHash"
+ },
+ {
+ "name" : "hashmapLock"
+ },
+ {
+ "name" : "hashmapPut"
+ },
+ {
+ "name" : "hashmapRemove"
+ },
+ {
+ "name" : "hashmapUnlock"
+ },
+ {
+ "name" : "klog_set_level"
+ },
+ {
+ "name" : "klog_write"
+ },
+ {
+ "name" : "klog_writev"
+ },
+ {
+ "name" : "load_canned_fs_config"
+ },
+ {
+ "name" : "load_file"
+ },
+ {
+ "name" : "multiuser_convert_sdk_sandbox_to_app_uid"
+ },
+ {
+ "name" : "multiuser_get_app_id"
+ },
+ {
+ "name" : "multiuser_get_cache_gid"
+ },
+ {
+ "name" : "multiuser_get_ext_cache_gid"
+ },
+ {
+ "name" : "multiuser_get_ext_gid"
+ },
+ {
+ "name" : "multiuser_get_sdk_sandbox_uid"
+ },
+ {
+ "name" : "multiuser_get_shared_app_gid"
+ },
+ {
+ "name" : "multiuser_get_shared_gid"
+ },
+ {
+ "name" : "multiuser_get_uid"
+ },
+ {
+ "name" : "multiuser_get_user_id"
+ },
+ {
+ "name" : "native_handle_clone"
+ },
+ {
+ "name" : "native_handle_close"
+ },
+ {
+ "name" : "native_handle_close_with_tag"
+ },
+ {
+ "name" : "native_handle_create"
+ },
+ {
+ "name" : "native_handle_delete"
+ },
+ {
+ "name" : "native_handle_init"
+ },
+ {
+ "name" : "native_handle_set_fdsan_tag"
+ },
+ {
+ "name" : "native_handle_unset_fdsan_tag"
+ },
+ {
+ "name" : "partition_wiped"
+ },
+ {
+ "name" : "property_get"
+ },
+ {
+ "name" : "property_get_bool"
+ },
+ {
+ "name" : "property_get_int32"
+ },
+ {
+ "name" : "property_get_int64"
+ },
+ {
+ "name" : "property_list"
+ },
+ {
+ "name" : "property_set"
+ },
+ {
+ "name" : "record_stream_free"
+ },
+ {
+ "name" : "record_stream_get_next"
+ },
+ {
+ "name" : "record_stream_new"
+ },
+ {
+ "name" : "socket_close"
+ },
+ {
+ "name" : "socket_get_local_port"
+ },
+ {
+ "name" : "socket_inaddr_any_server"
+ },
+ {
+ "name" : "socket_local_client"
+ },
+ {
+ "name" : "socket_local_client_connect"
+ },
+ {
+ "name" : "socket_local_server"
+ },
+ {
+ "name" : "socket_local_server_bind"
+ },
+ {
+ "name" : "socket_network_client"
+ },
+ {
+ "name" : "socket_network_client_timeout"
+ },
+ {
+ "name" : "socket_send_buffers"
+ },
+ {
+ "name" : "str_parms_add_float"
+ },
+ {
+ "name" : "str_parms_add_int"
+ },
+ {
+ "name" : "str_parms_add_str"
+ },
+ {
+ "name" : "str_parms_create"
+ },
+ {
+ "name" : "str_parms_create_str"
+ },
+ {
+ "name" : "str_parms_del"
+ },
+ {
+ "name" : "str_parms_destroy"
+ },
+ {
+ "name" : "str_parms_dump"
+ },
+ {
+ "name" : "str_parms_get_float"
+ },
+ {
+ "name" : "str_parms_get_int"
+ },
+ {
+ "name" : "str_parms_get_str"
+ },
+ {
+ "name" : "str_parms_has_key"
+ },
+ {
+ "name" : "str_parms_to_str"
+ },
+ {
+ "name" : "uevent_kernel_multicast_recv"
+ },
+ {
+ "name" : "uevent_kernel_multicast_uid_recv"
+ },
+ {
+ "name" : "uevent_kernel_recv"
+ },
+ {
+ "name" : "uevent_open_socket"
+ }
+ ],
+ "elf_objects" :
+ [
+ {
+ "binding" : "weak",
+ "name" : "_ZTCNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE0_NS_13basic_istreamIcS2_EE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTTNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE"
+ },
+ {
+ "name" : "atrace_enabled_tags"
+ },
+ {
+ "name" : "atrace_is_ready"
+ },
+ {
+ "name" : "atrace_marker_fd"
+ }
+ ],
+ "enum_types" :
+ [
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "IoSchedClass_NONE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "IoSchedClass_RT"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "IoSchedClass_BE"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "IoSchedClass_IDLE"
+ }
+ ],
+ "linker_set_key" : "_ZTI12IoSchedClass",
+ "name" : "IoSchedClass",
+ "referenced_type" : "_ZTI12IoSchedClass",
+ "self_type" : "_ZTI12IoSchedClass",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h",
+ "underlying_type" : "_ZTIj"
+ }
+ ],
+ "function_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFbPvS_E",
+ "name" : "bool (void *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFbPvS_E",
+ "return_type" : "_ZTIb",
+ "self_type" : "_ZTIFbPvS_E",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFbPvS_S_E",
+ "name" : "bool (void *, void *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFbPvS_S_E",
+ "return_type" : "_ZTIb",
+ "self_type" : "_ZTIFbPvS_S_E",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPvE",
+ "name" : "int (void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPvE",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPvE",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFvPKcS0_PvE",
+ "name" : "void (const char *, const char *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFvPKcS0_PvE",
+ "return_type" : "_ZTIv",
+ "self_type" : "_ZTIFvPKcS0_PvE",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ }
+ ],
+ "functions" :
+ [
+ {
+ "function_name" : "android_get_control_file",
+ "linker_set_key" : "android_get_control_file",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/android_get_control_file.h"
+ },
+ {
+ "function_name" : "android_get_control_socket",
+ "linker_set_key" : "android_get_control_socket",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "android_get_ioprio",
+ "linker_set_key" : "android_get_ioprio",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIP12IoSchedClass"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "function_name" : "android_reboot",
+ "linker_set_key" : "android_reboot",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/android_reboot.h"
+ },
+ {
+ "function_name" : "android_set_ioprio",
+ "linker_set_key" : "android_set_ioprio",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTI12IoSchedClass"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "function_name" : "ashmem_create_region",
+ "linker_set_key" : "ashmem_create_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_get_size_region",
+ "linker_set_key" : "ashmem_get_size_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_pin_region",
+ "linker_set_key" : "ashmem_pin_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_set_prot_region",
+ "linker_set_key" : "ashmem_set_prot_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_unpin_region",
+ "linker_set_key" : "ashmem_unpin_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_valid",
+ "linker_set_key" : "ashmem_valid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "atrace_async_begin_body",
+ "linker_set_key" : "atrace_async_begin_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_async_end_body",
+ "linker_set_key" : "atrace_async_end_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_async_for_track_begin_body",
+ "linker_set_key" : "atrace_async_for_track_begin_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_async_for_track_end_body",
+ "linker_set_key" : "atrace_async_for_track_end_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_begin_body",
+ "linker_set_key" : "atrace_begin_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_end_body",
+ "linker_set_key" : "atrace_end_body",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_get_enabled_tags",
+ "linker_set_key" : "atrace_get_enabled_tags",
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_init",
+ "linker_set_key" : "atrace_init",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_instant_body",
+ "linker_set_key" : "atrace_instant_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_instant_for_track_body",
+ "linker_set_key" : "atrace_instant_for_track_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_int64_body",
+ "linker_set_key" : "atrace_int64_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIl"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_int_body",
+ "linker_set_key" : "atrace_int_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_set_tracing_enabled",
+ "linker_set_key" : "atrace_set_tracing_enabled",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_setup",
+ "linker_set_key" : "atrace_setup",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_update_tags",
+ "linker_set_key" : "atrace_update_tags",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "canned_fs_config",
+ "linker_set_key" : "canned_fs_config",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/private/canned_fs_config.h"
+ },
+ {
+ "function_name" : "config_bool",
+ "linker_set_key" : "config_bool",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_find",
+ "linker_set_key" : "config_find",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIP5cnode",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_free",
+ "linker_set_key" : "config_free",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_load",
+ "linker_set_key" : "config_load",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_load_file",
+ "linker_set_key" : "config_load_file",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_node",
+ "linker_set_key" : "config_node",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIP5cnode",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_set",
+ "linker_set_key" : "config_set",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_str",
+ "linker_set_key" : "config_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIPKc",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "fs_config",
+ "linker_set_key" : "fs_config",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/private/fs_config.h"
+ },
+ {
+ "function_name" : "fs_mkdirs",
+ "linker_set_key" : "fs_mkdirs",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_prepare_dir",
+ "linker_set_key" : "fs_prepare_dir",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_prepare_dir_strict",
+ "linker_set_key" : "fs_prepare_dir_strict",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_prepare_file_strict",
+ "linker_set_key" : "fs_prepare_file_strict",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_read_atomic_int",
+ "linker_set_key" : "fs_read_atomic_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_write_atomic_int",
+ "linker_set_key" : "fs_write_atomic_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "hashmapCreate",
+ "linker_set_key" : "hashmapCreate",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPFbPvS_E"
+ }
+ ],
+ "return_type" : "_ZTIP7Hashmap",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapForEach",
+ "linker_set_key" : "hashmapForEach",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPFbPvS_S_E"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapFree",
+ "linker_set_key" : "hashmapFree",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapGet",
+ "linker_set_key" : "hashmapGet",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapHash",
+ "linker_set_key" : "hashmapHash",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapLock",
+ "linker_set_key" : "hashmapLock",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapPut",
+ "linker_set_key" : "hashmapPut",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapRemove",
+ "linker_set_key" : "hashmapRemove",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapUnlock",
+ "linker_set_key" : "hashmapUnlock",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "klog_set_level",
+ "linker_set_key" : "klog_set_level",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "function_name" : "klog_write",
+ "linker_set_key" : "klog_write",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "function_name" : "klog_writev",
+ "linker_set_key" : "klog_writev",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPK5iovec"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "function_name" : "load_canned_fs_config",
+ "linker_set_key" : "load_canned_fs_config",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/private/canned_fs_config.h"
+ },
+ {
+ "function_name" : "load_file",
+ "linker_set_key" : "load_file",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/misc.h"
+ },
+ {
+ "function_name" : "multiuser_convert_sdk_sandbox_to_app_uid",
+ "linker_set_key" : "multiuser_convert_sdk_sandbox_to_app_uid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_app_id",
+ "linker_set_key" : "multiuser_get_app_id",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_cache_gid",
+ "linker_set_key" : "multiuser_get_cache_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_ext_cache_gid",
+ "linker_set_key" : "multiuser_get_ext_cache_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_ext_gid",
+ "linker_set_key" : "multiuser_get_ext_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_sdk_sandbox_uid",
+ "linker_set_key" : "multiuser_get_sdk_sandbox_uid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_shared_app_gid",
+ "linker_set_key" : "multiuser_get_shared_app_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_shared_gid",
+ "linker_set_key" : "multiuser_get_shared_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_uid",
+ "linker_set_key" : "multiuser_get_uid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_user_id",
+ "linker_set_key" : "multiuser_get_user_id",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "native_handle_clone",
+ "linker_set_key" : "native_handle_clone",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIP13native_handle",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_close",
+ "linker_set_key" : "native_handle_close",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_close_with_tag",
+ "linker_set_key" : "native_handle_close_with_tag",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_create",
+ "linker_set_key" : "native_handle_create",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIP13native_handle",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_delete",
+ "linker_set_key" : "native_handle_delete",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_init",
+ "linker_set_key" : "native_handle_init",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIP13native_handle",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_set_fdsan_tag",
+ "linker_set_key" : "native_handle_set_fdsan_tag",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_unset_fdsan_tag",
+ "linker_set_key" : "native_handle_unset_fdsan_tag",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "partition_wiped",
+ "linker_set_key" : "partition_wiped",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/partition_utils.h"
+ },
+ {
+ "function_name" : "property_get",
+ "linker_set_key" : "property_get",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_get_bool",
+ "linker_set_key" : "property_get_bool",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIa"
+ }
+ ],
+ "return_type" : "_ZTIa",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_get_int32",
+ "linker_set_key" : "property_get_int32",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_get_int64",
+ "linker_set_key" : "property_get_int64",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIl"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_list",
+ "linker_set_key" : "property_list",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFvPKcS0_PvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_set",
+ "linker_set_key" : "property_set",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "record_stream_free",
+ "linker_set_key" : "record_stream_free",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP12RecordStream"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "function_name" : "record_stream_get_next",
+ "linker_set_key" : "record_stream_get_next",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP12RecordStream"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ },
+ {
+ "referenced_type" : "_ZTIPm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "function_name" : "record_stream_new",
+ "linker_set_key" : "record_stream_new",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIP12RecordStream",
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "function_name" : "socket_close",
+ "linker_set_key" : "socket_close",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_get_local_port",
+ "linker_set_key" : "socket_get_local_port",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_inaddr_any_server",
+ "linker_set_key" : "socket_inaddr_any_server",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_client",
+ "linker_set_key" : "socket_local_client",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_client_connect",
+ "linker_set_key" : "socket_local_client_connect",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_server",
+ "linker_set_key" : "socket_local_server",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_server_bind",
+ "linker_set_key" : "socket_local_server_bind",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_network_client",
+ "linker_set_key" : "socket_network_client",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_network_client_timeout",
+ "linker_set_key" : "socket_network_client_timeout",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_send_buffers",
+ "linker_set_key" : "socket_send_buffers",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPK22cutils_socket_buffer_t"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "str_parms_add_float",
+ "linker_set_key" : "str_parms_add_float",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_add_int",
+ "linker_set_key" : "str_parms_add_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_add_str",
+ "linker_set_key" : "str_parms_add_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_create",
+ "linker_set_key" : "str_parms_create",
+ "return_type" : "_ZTIP9str_parms",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_create_str",
+ "linker_set_key" : "str_parms_create_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIP9str_parms",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_del",
+ "linker_set_key" : "str_parms_del",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_destroy",
+ "linker_set_key" : "str_parms_destroy",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_dump",
+ "linker_set_key" : "str_parms_dump",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_get_float",
+ "linker_set_key" : "str_parms_get_float",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPf"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_get_int",
+ "linker_set_key" : "str_parms_get_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_get_str",
+ "linker_set_key" : "str_parms_get_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_has_key",
+ "linker_set_key" : "str_parms_has_key",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_to_str",
+ "linker_set_key" : "str_parms_to_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "uevent_kernel_multicast_recv",
+ "linker_set_key" : "uevent_kernel_multicast_recv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ },
+ {
+ "function_name" : "uevent_kernel_multicast_uid_recv",
+ "linker_set_key" : "uevent_kernel_multicast_uid_recv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ },
+ {
+ "function_name" : "uevent_kernel_recv",
+ "linker_set_key" : "uevent_kernel_recv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ },
+ {
+ "function_name" : "uevent_open_socket",
+ "linker_set_key" : "uevent_open_socket",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ }
+ ],
+ "global_vars" :
+ [
+ {
+ "linker_set_key" : "atrace_enabled_tags",
+ "name" : "atrace_enabled_tags",
+ "referenced_type" : "_ZTIm",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "linker_set_key" : "atrace_is_ready",
+ "name" : "atrace_is_ready",
+ "referenced_type" : "_ZTINSt3__16atomicIbEE",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "linker_set_key" : "atrace_marker_fd",
+ "name" : "atrace_marker_fd",
+ "referenced_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ }
+ ],
+ "lvalue_reference_types" : [],
+ "pointer_types" :
+ [
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP12IoSchedClass",
+ "name" : "IoSchedClass *",
+ "referenced_type" : "_ZTI12IoSchedClass",
+ "self_type" : "_ZTIP12IoSchedClass",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP12RecordStream",
+ "name" : "RecordStream *",
+ "referenced_type" : "_ZTI12RecordStream",
+ "self_type" : "_ZTIP12RecordStream",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP13native_handle",
+ "name" : "native_handle *",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTIP13native_handle",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP5cnode",
+ "name" : "cnode *",
+ "referenced_type" : "_ZTI5cnode",
+ "self_type" : "_ZTIP5cnode",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP7Hashmap",
+ "name" : "Hashmap *",
+ "referenced_type" : "_ZTI7Hashmap",
+ "self_type" : "_ZTIP7Hashmap",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP9str_parms",
+ "name" : "str_parms *",
+ "referenced_type" : "_ZTI9str_parms",
+ "self_type" : "_ZTIP9str_parms",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFbPvS_E",
+ "name" : "bool (*)(void *, void *)",
+ "referenced_type" : "_ZTIFbPvS_E",
+ "self_type" : "_ZTIPFbPvS_E",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFbPvS_S_E",
+ "name" : "bool (*)(void *, void *, void *)",
+ "referenced_type" : "_ZTIFbPvS_S_E",
+ "self_type" : "_ZTIPFbPvS_S_E",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFiPvE",
+ "name" : "int (*)(void *)",
+ "referenced_type" : "_ZTIFiPvE",
+ "self_type" : "_ZTIPFiPvE",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFvPKcS0_PvE",
+ "name" : "void (*)(const char *, const char *, void *)",
+ "referenced_type" : "_ZTIFvPKcS0_PvE",
+ "self_type" : "_ZTIPFvPKcS0_PvE",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPK13native_handle",
+ "name" : "const native_handle *",
+ "referenced_type" : "_ZTIK13native_handle",
+ "self_type" : "_ZTIPK13native_handle",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPK22cutils_socket_buffer_t",
+ "name" : "const cutils_socket_buffer_t *",
+ "referenced_type" : "_ZTIK22cutils_socket_buffer_t",
+ "self_type" : "_ZTIPK22cutils_socket_buffer_t",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPK5iovec",
+ "name" : "const iovec *",
+ "referenced_type" : "_ZTIK5iovec",
+ "self_type" : "_ZTIPK5iovec",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKc",
+ "name" : "const char *",
+ "referenced_type" : "_ZTIKc",
+ "self_type" : "_ZTIPKc",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKv",
+ "name" : "const void *",
+ "referenced_type" : "_ZTIKv",
+ "self_type" : "_ZTIPKv",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPPv",
+ "name" : "void **",
+ "referenced_type" : "_ZTIPv",
+ "self_type" : "_ZTIPPv",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPc",
+ "name" : "char *",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIPc",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPf",
+ "name" : "float *",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIPf",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPi",
+ "name" : "int *",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIPi",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPj",
+ "name" : "unsigned int *",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIPj",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/misc.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPm",
+ "name" : "unsigned long *",
+ "referenced_type" : "_ZTIm",
+ "self_type" : "_ZTIPm",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPv",
+ "name" : "void *",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIPv",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/misc.h"
+ }
+ ],
+ "qualified_types" :
+ [
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK13native_handle",
+ "name" : "const native_handle",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTIK13native_handle",
+ "size" : 12,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK22cutils_socket_buffer_t",
+ "name" : "const cutils_socket_buffer_t",
+ "referenced_type" : "_ZTI22cutils_socket_buffer_t",
+ "self_type" : "_ZTIK22cutils_socket_buffer_t",
+ "size" : 16,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK5iovec",
+ "name" : "const iovec",
+ "referenced_type" : "_ZTI5iovec",
+ "self_type" : "_ZTIK5iovec",
+ "size" : 16,
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKc",
+ "name" : "const char",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIKc",
+ "size" : 1,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKv",
+ "name" : "const void",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIKv",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ }
+ ],
+ "record_types" :
+ [
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "version",
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "numFds",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "numInts",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "data",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIA0_i"
+ }
+ ],
+ "linker_set_key" : "_ZTI13native_handle",
+ "name" : "native_handle",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTI13native_handle",
+ "size" : 12,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "data",
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "field_name" : "length",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "linker_set_key" : "_ZTI22cutils_socket_buffer_t",
+ "name" : "cutils_socket_buffer_t",
+ "referenced_type" : "_ZTI22cutils_socket_buffer_t",
+ "self_type" : "_ZTI22cutils_socket_buffer_t",
+ "size" : 16,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "next",
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "field_name" : "first_child",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "field_name" : "last_child",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "field_name" : "name",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "field_name" : "value",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTI5cnode",
+ "name" : "cnode",
+ "referenced_type" : "_ZTI5cnode",
+ "self_type" : "_ZTI5cnode",
+ "size" : 40,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ }
+ ],
+ "rvalue_reference_types" : []
+}
diff --git a/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump b/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
new file mode 100644
index 0000000..f612fb9
--- /dev/null
+++ b/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
@@ -0,0 +1,2700 @@
+{
+ "array_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIA0_i",
+ "name" : "int[0]",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIA0_i",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ }
+ ],
+ "builtin_types" :
+ [
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIa",
+ "name" : "signed char",
+ "referenced_type" : "_ZTIa",
+ "self_type" : "_ZTIa",
+ "size" : 1
+ },
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIb",
+ "name" : "bool",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIb",
+ "size" : 1
+ },
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIc",
+ "name" : "char",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIc",
+ "size" : 1
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIf",
+ "name" : "float",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIf",
+ "size" : 4
+ },
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIi",
+ "name" : "int",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIi",
+ "size" : 4
+ },
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIj",
+ "name" : "unsigned int",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIj",
+ "size" : 4
+ },
+ {
+ "alignment" : 2,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIt",
+ "name" : "unsigned short",
+ "referenced_type" : "_ZTIt",
+ "self_type" : "_ZTIt",
+ "size" : 2
+ },
+ {
+ "linker_set_key" : "_ZTIv",
+ "name" : "void",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIv"
+ },
+ {
+ "alignment" : 8,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIx",
+ "name" : "long long",
+ "referenced_type" : "_ZTIx",
+ "self_type" : "_ZTIx",
+ "size" : 8
+ },
+ {
+ "alignment" : 8,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIy",
+ "name" : "unsigned long long",
+ "referenced_type" : "_ZTIy",
+ "self_type" : "_ZTIy",
+ "size" : 8
+ }
+ ],
+ "elf_functions" :
+ [
+ {
+ "name" : "_Z23socket_make_sockaddr_unPKciP11sockaddr_unPi"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZN7android4base4TrimIRNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEES8_OT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4syncEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE5imbueERKNS_6localeE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE6setbufEPci"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE7seekoffExNS_8ios_base7seekdirEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE7seekposENS_4fposI9mbstate_tEEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE8overflowEi"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE9pbackfailEi"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE9underflowEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEEC2Ev"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED0Ev"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED2Ev"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__16vectorI5EntryNS_9allocatorIS1_EEE24__emplace_back_slow_pathIJS1_EEEvDpOT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__17getlineIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS_13basic_istreamIT_T0_EES9_RNS_12basic_stringIS6_S7_T1_EES6_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc"
+ },
+ {
+ "name" : "android_get_control_file"
+ },
+ {
+ "name" : "android_get_control_socket"
+ },
+ {
+ "name" : "android_get_ioprio"
+ },
+ {
+ "name" : "android_reboot"
+ },
+ {
+ "name" : "android_set_ioprio"
+ },
+ {
+ "name" : "ashmem_create_region"
+ },
+ {
+ "name" : "ashmem_get_size_region"
+ },
+ {
+ "name" : "ashmem_pin_region"
+ },
+ {
+ "name" : "ashmem_set_prot_region"
+ },
+ {
+ "name" : "ashmem_unpin_region"
+ },
+ {
+ "name" : "ashmem_valid"
+ },
+ {
+ "name" : "atrace_async_begin_body"
+ },
+ {
+ "name" : "atrace_async_end_body"
+ },
+ {
+ "name" : "atrace_async_for_track_begin_body"
+ },
+ {
+ "name" : "atrace_async_for_track_end_body"
+ },
+ {
+ "name" : "atrace_begin_body"
+ },
+ {
+ "name" : "atrace_end_body"
+ },
+ {
+ "name" : "atrace_get_enabled_tags"
+ },
+ {
+ "name" : "atrace_init"
+ },
+ {
+ "name" : "atrace_instant_body"
+ },
+ {
+ "name" : "atrace_instant_for_track_body"
+ },
+ {
+ "name" : "atrace_int64_body"
+ },
+ {
+ "name" : "atrace_int_body"
+ },
+ {
+ "name" : "atrace_set_tracing_enabled"
+ },
+ {
+ "name" : "atrace_setup"
+ },
+ {
+ "name" : "atrace_update_tags"
+ },
+ {
+ "name" : "canned_fs_config"
+ },
+ {
+ "name" : "config_bool"
+ },
+ {
+ "name" : "config_find"
+ },
+ {
+ "name" : "config_free"
+ },
+ {
+ "name" : "config_load"
+ },
+ {
+ "name" : "config_load_file"
+ },
+ {
+ "name" : "config_node"
+ },
+ {
+ "name" : "config_set"
+ },
+ {
+ "name" : "config_str"
+ },
+ {
+ "name" : "fs_config"
+ },
+ {
+ "name" : "fs_mkdirs"
+ },
+ {
+ "name" : "fs_prepare_dir"
+ },
+ {
+ "name" : "fs_prepare_dir_strict"
+ },
+ {
+ "name" : "fs_prepare_file_strict"
+ },
+ {
+ "name" : "fs_read_atomic_int"
+ },
+ {
+ "name" : "fs_write_atomic_int"
+ },
+ {
+ "name" : "hashmapCreate"
+ },
+ {
+ "name" : "hashmapForEach"
+ },
+ {
+ "name" : "hashmapFree"
+ },
+ {
+ "name" : "hashmapGet"
+ },
+ {
+ "name" : "hashmapHash"
+ },
+ {
+ "name" : "hashmapLock"
+ },
+ {
+ "name" : "hashmapPut"
+ },
+ {
+ "name" : "hashmapRemove"
+ },
+ {
+ "name" : "hashmapUnlock"
+ },
+ {
+ "name" : "klog_set_level"
+ },
+ {
+ "name" : "klog_write"
+ },
+ {
+ "name" : "klog_writev"
+ },
+ {
+ "name" : "load_canned_fs_config"
+ },
+ {
+ "name" : "load_file"
+ },
+ {
+ "name" : "multiuser_convert_sdk_sandbox_to_app_uid"
+ },
+ {
+ "name" : "multiuser_get_app_id"
+ },
+ {
+ "name" : "multiuser_get_cache_gid"
+ },
+ {
+ "name" : "multiuser_get_ext_cache_gid"
+ },
+ {
+ "name" : "multiuser_get_ext_gid"
+ },
+ {
+ "name" : "multiuser_get_sdk_sandbox_uid"
+ },
+ {
+ "name" : "multiuser_get_shared_app_gid"
+ },
+ {
+ "name" : "multiuser_get_shared_gid"
+ },
+ {
+ "name" : "multiuser_get_uid"
+ },
+ {
+ "name" : "multiuser_get_user_id"
+ },
+ {
+ "name" : "native_handle_clone"
+ },
+ {
+ "name" : "native_handle_close"
+ },
+ {
+ "name" : "native_handle_close_with_tag"
+ },
+ {
+ "name" : "native_handle_create"
+ },
+ {
+ "name" : "native_handle_delete"
+ },
+ {
+ "name" : "native_handle_init"
+ },
+ {
+ "name" : "native_handle_set_fdsan_tag"
+ },
+ {
+ "name" : "native_handle_unset_fdsan_tag"
+ },
+ {
+ "name" : "partition_wiped"
+ },
+ {
+ "name" : "property_get"
+ },
+ {
+ "name" : "property_get_bool"
+ },
+ {
+ "name" : "property_get_int32"
+ },
+ {
+ "name" : "property_get_int64"
+ },
+ {
+ "name" : "property_list"
+ },
+ {
+ "name" : "property_set"
+ },
+ {
+ "name" : "record_stream_free"
+ },
+ {
+ "name" : "record_stream_get_next"
+ },
+ {
+ "name" : "record_stream_new"
+ },
+ {
+ "name" : "socket_close"
+ },
+ {
+ "name" : "socket_get_local_port"
+ },
+ {
+ "name" : "socket_inaddr_any_server"
+ },
+ {
+ "name" : "socket_local_client"
+ },
+ {
+ "name" : "socket_local_client_connect"
+ },
+ {
+ "name" : "socket_local_server"
+ },
+ {
+ "name" : "socket_local_server_bind"
+ },
+ {
+ "name" : "socket_network_client"
+ },
+ {
+ "name" : "socket_network_client_timeout"
+ },
+ {
+ "name" : "socket_send_buffers"
+ },
+ {
+ "name" : "str_parms_add_float"
+ },
+ {
+ "name" : "str_parms_add_int"
+ },
+ {
+ "name" : "str_parms_add_str"
+ },
+ {
+ "name" : "str_parms_create"
+ },
+ {
+ "name" : "str_parms_create_str"
+ },
+ {
+ "name" : "str_parms_del"
+ },
+ {
+ "name" : "str_parms_destroy"
+ },
+ {
+ "name" : "str_parms_dump"
+ },
+ {
+ "name" : "str_parms_get_float"
+ },
+ {
+ "name" : "str_parms_get_int"
+ },
+ {
+ "name" : "str_parms_get_str"
+ },
+ {
+ "name" : "str_parms_has_key"
+ },
+ {
+ "name" : "str_parms_to_str"
+ },
+ {
+ "name" : "uevent_kernel_multicast_recv"
+ },
+ {
+ "name" : "uevent_kernel_multicast_uid_recv"
+ },
+ {
+ "name" : "uevent_kernel_recv"
+ },
+ {
+ "name" : "uevent_open_socket"
+ }
+ ],
+ "elf_objects" :
+ [
+ {
+ "binding" : "weak",
+ "name" : "_ZTCNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE0_NS_13basic_istreamIcS2_EE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTTNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE"
+ },
+ {
+ "name" : "atrace_enabled_tags"
+ },
+ {
+ "name" : "atrace_is_ready"
+ },
+ {
+ "name" : "atrace_marker_fd"
+ }
+ ],
+ "enum_types" :
+ [
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "IoSchedClass_NONE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "IoSchedClass_RT"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "IoSchedClass_BE"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "IoSchedClass_IDLE"
+ }
+ ],
+ "linker_set_key" : "_ZTI12IoSchedClass",
+ "name" : "IoSchedClass",
+ "referenced_type" : "_ZTI12IoSchedClass",
+ "self_type" : "_ZTI12IoSchedClass",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h",
+ "underlying_type" : "_ZTIj"
+ }
+ ],
+ "function_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFbPvS_E",
+ "name" : "bool (void *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFbPvS_E",
+ "return_type" : "_ZTIb",
+ "self_type" : "_ZTIFbPvS_E",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFbPvS_S_E",
+ "name" : "bool (void *, void *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFbPvS_S_E",
+ "return_type" : "_ZTIb",
+ "self_type" : "_ZTIFbPvS_S_E",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPvE",
+ "name" : "int (void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPvE",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPvE",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFvPKcS0_PvE",
+ "name" : "void (const char *, const char *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFvPKcS0_PvE",
+ "return_type" : "_ZTIv",
+ "self_type" : "_ZTIFvPKcS0_PvE",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ }
+ ],
+ "functions" :
+ [
+ {
+ "function_name" : "android_get_control_file",
+ "linker_set_key" : "android_get_control_file",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/android_get_control_file.h"
+ },
+ {
+ "function_name" : "android_get_control_socket",
+ "linker_set_key" : "android_get_control_socket",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "android_get_ioprio",
+ "linker_set_key" : "android_get_ioprio",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIP12IoSchedClass"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "function_name" : "android_reboot",
+ "linker_set_key" : "android_reboot",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/android_reboot.h"
+ },
+ {
+ "function_name" : "android_set_ioprio",
+ "linker_set_key" : "android_set_ioprio",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTI12IoSchedClass"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "function_name" : "ashmem_create_region",
+ "linker_set_key" : "ashmem_create_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_get_size_region",
+ "linker_set_key" : "ashmem_get_size_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_pin_region",
+ "linker_set_key" : "ashmem_pin_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_set_prot_region",
+ "linker_set_key" : "ashmem_set_prot_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_unpin_region",
+ "linker_set_key" : "ashmem_unpin_region",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "ashmem_valid",
+ "linker_set_key" : "ashmem_valid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/ashmem.h"
+ },
+ {
+ "function_name" : "atrace_async_begin_body",
+ "linker_set_key" : "atrace_async_begin_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_async_end_body",
+ "linker_set_key" : "atrace_async_end_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_async_for_track_begin_body",
+ "linker_set_key" : "atrace_async_for_track_begin_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_async_for_track_end_body",
+ "linker_set_key" : "atrace_async_for_track_end_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_begin_body",
+ "linker_set_key" : "atrace_begin_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_end_body",
+ "linker_set_key" : "atrace_end_body",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_get_enabled_tags",
+ "linker_set_key" : "atrace_get_enabled_tags",
+ "return_type" : "_ZTIy",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_init",
+ "linker_set_key" : "atrace_init",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_instant_body",
+ "linker_set_key" : "atrace_instant_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_instant_for_track_body",
+ "linker_set_key" : "atrace_instant_for_track_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_int64_body",
+ "linker_set_key" : "atrace_int64_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIx"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_int_body",
+ "linker_set_key" : "atrace_int_body",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_set_tracing_enabled",
+ "linker_set_key" : "atrace_set_tracing_enabled",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_setup",
+ "linker_set_key" : "atrace_setup",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "atrace_update_tags",
+ "linker_set_key" : "atrace_update_tags",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "function_name" : "canned_fs_config",
+ "linker_set_key" : "canned_fs_config",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPy"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/private/canned_fs_config.h"
+ },
+ {
+ "function_name" : "config_bool",
+ "linker_set_key" : "config_bool",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_find",
+ "linker_set_key" : "config_find",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIP5cnode",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_free",
+ "linker_set_key" : "config_free",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_load",
+ "linker_set_key" : "config_load",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_load_file",
+ "linker_set_key" : "config_load_file",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_node",
+ "linker_set_key" : "config_node",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIP5cnode",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_set",
+ "linker_set_key" : "config_set",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "config_str",
+ "linker_set_key" : "config_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIPKc",
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "function_name" : "fs_config",
+ "linker_set_key" : "fs_config",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ },
+ {
+ "referenced_type" : "_ZTIPy"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/private/fs_config.h"
+ },
+ {
+ "function_name" : "fs_mkdirs",
+ "linker_set_key" : "fs_mkdirs",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIt"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_prepare_dir",
+ "linker_set_key" : "fs_prepare_dir",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_prepare_dir_strict",
+ "linker_set_key" : "fs_prepare_dir_strict",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_prepare_file_strict",
+ "linker_set_key" : "fs_prepare_file_strict",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_read_atomic_int",
+ "linker_set_key" : "fs_read_atomic_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "fs_write_atomic_int",
+ "linker_set_key" : "fs_write_atomic_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/fs.h"
+ },
+ {
+ "function_name" : "hashmapCreate",
+ "linker_set_key" : "hashmapCreate",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPFbPvS_E"
+ }
+ ],
+ "return_type" : "_ZTIP7Hashmap",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapForEach",
+ "linker_set_key" : "hashmapForEach",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPFbPvS_S_E"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapFree",
+ "linker_set_key" : "hashmapFree",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapGet",
+ "linker_set_key" : "hashmapGet",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapHash",
+ "linker_set_key" : "hashmapHash",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapLock",
+ "linker_set_key" : "hashmapLock",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapPut",
+ "linker_set_key" : "hashmapPut",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapRemove",
+ "linker_set_key" : "hashmapRemove",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "hashmapUnlock",
+ "linker_set_key" : "hashmapUnlock",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP7Hashmap"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "function_name" : "klog_set_level",
+ "linker_set_key" : "klog_set_level",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "function_name" : "klog_write",
+ "linker_set_key" : "klog_write",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "function_name" : "klog_writev",
+ "linker_set_key" : "klog_writev",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPK5iovec"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "function_name" : "load_canned_fs_config",
+ "linker_set_key" : "load_canned_fs_config",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/private/canned_fs_config.h"
+ },
+ {
+ "function_name" : "load_file",
+ "linker_set_key" : "load_file",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libcutils/include/cutils/misc.h"
+ },
+ {
+ "function_name" : "multiuser_convert_sdk_sandbox_to_app_uid",
+ "linker_set_key" : "multiuser_convert_sdk_sandbox_to_app_uid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_app_id",
+ "linker_set_key" : "multiuser_get_app_id",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_cache_gid",
+ "linker_set_key" : "multiuser_get_cache_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_ext_cache_gid",
+ "linker_set_key" : "multiuser_get_ext_cache_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_ext_gid",
+ "linker_set_key" : "multiuser_get_ext_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_sdk_sandbox_uid",
+ "linker_set_key" : "multiuser_get_sdk_sandbox_uid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_shared_app_gid",
+ "linker_set_key" : "multiuser_get_shared_app_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_shared_gid",
+ "linker_set_key" : "multiuser_get_shared_gid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_uid",
+ "linker_set_key" : "multiuser_get_uid",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "multiuser_get_user_id",
+ "linker_set_key" : "multiuser_get_user_id",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libcutils/include/cutils/multiuser.h"
+ },
+ {
+ "function_name" : "native_handle_clone",
+ "linker_set_key" : "native_handle_clone",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIP13native_handle",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_close",
+ "linker_set_key" : "native_handle_close",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_close_with_tag",
+ "linker_set_key" : "native_handle_close_with_tag",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_create",
+ "linker_set_key" : "native_handle_create",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIP13native_handle",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_delete",
+ "linker_set_key" : "native_handle_delete",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_init",
+ "linker_set_key" : "native_handle_init",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIP13native_handle",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_set_fdsan_tag",
+ "linker_set_key" : "native_handle_set_fdsan_tag",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "native_handle_unset_fdsan_tag",
+ "linker_set_key" : "native_handle_unset_fdsan_tag",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPK13native_handle"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "function_name" : "partition_wiped",
+ "linker_set_key" : "partition_wiped",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/partition_utils.h"
+ },
+ {
+ "function_name" : "property_get",
+ "linker_set_key" : "property_get",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_get_bool",
+ "linker_set_key" : "property_get_bool",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIa"
+ }
+ ],
+ "return_type" : "_ZTIa",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_get_int32",
+ "linker_set_key" : "property_get_int32",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_get_int64",
+ "linker_set_key" : "property_get_int64",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIx"
+ }
+ ],
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_list",
+ "linker_set_key" : "property_list",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFvPKcS0_PvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "property_set",
+ "linker_set_key" : "property_set",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "function_name" : "record_stream_free",
+ "linker_set_key" : "record_stream_free",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP12RecordStream"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "function_name" : "record_stream_get_next",
+ "linker_set_key" : "record_stream_get_next",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP12RecordStream"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "function_name" : "record_stream_new",
+ "linker_set_key" : "record_stream_new",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIP12RecordStream",
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "function_name" : "socket_close",
+ "linker_set_key" : "socket_close",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_get_local_port",
+ "linker_set_key" : "socket_get_local_port",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_inaddr_any_server",
+ "linker_set_key" : "socket_inaddr_any_server",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_client",
+ "linker_set_key" : "socket_local_client",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_client_connect",
+ "linker_set_key" : "socket_local_client_connect",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_server",
+ "linker_set_key" : "socket_local_server",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_local_server_bind",
+ "linker_set_key" : "socket_local_server_bind",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_network_client",
+ "linker_set_key" : "socket_network_client",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_network_client_timeout",
+ "linker_set_key" : "socket_network_client_timeout",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "socket_send_buffers",
+ "linker_set_key" : "socket_send_buffers",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPK22cutils_socket_buffer_t"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "function_name" : "str_parms_add_float",
+ "linker_set_key" : "str_parms_add_float",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_add_int",
+ "linker_set_key" : "str_parms_add_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_add_str",
+ "linker_set_key" : "str_parms_add_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_create",
+ "linker_set_key" : "str_parms_create",
+ "return_type" : "_ZTIP9str_parms",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_create_str",
+ "linker_set_key" : "str_parms_create_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIP9str_parms",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_del",
+ "linker_set_key" : "str_parms_del",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_destroy",
+ "linker_set_key" : "str_parms_destroy",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_dump",
+ "linker_set_key" : "str_parms_dump",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_get_float",
+ "linker_set_key" : "str_parms_get_float",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPf"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_get_int",
+ "linker_set_key" : "str_parms_get_int",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_get_str",
+ "linker_set_key" : "str_parms_get_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_has_key",
+ "linker_set_key" : "str_parms_has_key",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "str_parms_to_str",
+ "linker_set_key" : "str_parms_to_str",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP9str_parms"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "function_name" : "uevent_kernel_multicast_recv",
+ "linker_set_key" : "uevent_kernel_multicast_recv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ },
+ {
+ "function_name" : "uevent_kernel_multicast_uid_recv",
+ "linker_set_key" : "uevent_kernel_multicast_uid_recv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ },
+ {
+ "function_name" : "uevent_kernel_recv",
+ "linker_set_key" : "uevent_kernel_recv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ },
+ {
+ "function_name" : "uevent_open_socket",
+ "linker_set_key" : "uevent_open_socket",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/uevent.h"
+ }
+ ],
+ "global_vars" :
+ [
+ {
+ "linker_set_key" : "atrace_enabled_tags",
+ "name" : "atrace_enabled_tags",
+ "referenced_type" : "_ZTIy",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "linker_set_key" : "atrace_is_ready",
+ "name" : "atrace_is_ready",
+ "referenced_type" : "_ZTINSt3__16atomicIbEE",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ },
+ {
+ "linker_set_key" : "atrace_marker_fd",
+ "name" : "atrace_marker_fd",
+ "referenced_type" : "_ZTIi",
+ "source_file" : "system/core/libcutils/include/cutils/trace.h"
+ }
+ ],
+ "lvalue_reference_types" : [],
+ "pointer_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP12IoSchedClass",
+ "name" : "IoSchedClass *",
+ "referenced_type" : "_ZTI12IoSchedClass",
+ "self_type" : "_ZTIP12IoSchedClass",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP12RecordStream",
+ "name" : "RecordStream *",
+ "referenced_type" : "_ZTI12RecordStream",
+ "self_type" : "_ZTIP12RecordStream",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP13native_handle",
+ "name" : "native_handle *",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTIP13native_handle",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP5cnode",
+ "name" : "cnode *",
+ "referenced_type" : "_ZTI5cnode",
+ "self_type" : "_ZTIP5cnode",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP7Hashmap",
+ "name" : "Hashmap *",
+ "referenced_type" : "_ZTI7Hashmap",
+ "self_type" : "_ZTIP7Hashmap",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP9str_parms",
+ "name" : "str_parms *",
+ "referenced_type" : "_ZTI9str_parms",
+ "self_type" : "_ZTIP9str_parms",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFbPvS_E",
+ "name" : "bool (*)(void *, void *)",
+ "referenced_type" : "_ZTIFbPvS_E",
+ "self_type" : "_ZTIPFbPvS_E",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFbPvS_S_E",
+ "name" : "bool (*)(void *, void *, void *)",
+ "referenced_type" : "_ZTIFbPvS_S_E",
+ "self_type" : "_ZTIPFbPvS_S_E",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFiPvE",
+ "name" : "int (*)(void *)",
+ "referenced_type" : "_ZTIFiPvE",
+ "self_type" : "_ZTIPFiPvE",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/hashmap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFvPKcS0_PvE",
+ "name" : "void (*)(const char *, const char *, void *)",
+ "referenced_type" : "_ZTIFvPKcS0_PvE",
+ "self_type" : "_ZTIPFvPKcS0_PvE",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/properties.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPK13native_handle",
+ "name" : "const native_handle *",
+ "referenced_type" : "_ZTIK13native_handle",
+ "self_type" : "_ZTIPK13native_handle",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPK22cutils_socket_buffer_t",
+ "name" : "const cutils_socket_buffer_t *",
+ "referenced_type" : "_ZTIK22cutils_socket_buffer_t",
+ "self_type" : "_ZTIPK22cutils_socket_buffer_t",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPK5iovec",
+ "name" : "const iovec *",
+ "referenced_type" : "_ZTIK5iovec",
+ "self_type" : "_ZTIPK5iovec",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKc",
+ "name" : "const char *",
+ "referenced_type" : "_ZTIKc",
+ "self_type" : "_ZTIPKc",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKv",
+ "name" : "const void *",
+ "referenced_type" : "_ZTIKv",
+ "self_type" : "_ZTIPKv",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPPv",
+ "name" : "void **",
+ "referenced_type" : "_ZTIPv",
+ "self_type" : "_ZTIPPv",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/record_stream.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPc",
+ "name" : "char *",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIPc",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPf",
+ "name" : "float *",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIPf",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/str_parms.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPi",
+ "name" : "int *",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIPi",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/iosched_policy.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPj",
+ "name" : "unsigned int *",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIPj",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/misc.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPv",
+ "name" : "void *",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIPv",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/cutils/misc.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPy",
+ "name" : "unsigned long long *",
+ "referenced_type" : "_ZTIy",
+ "self_type" : "_ZTIPy",
+ "size" : 4,
+ "source_file" : "system/core/libcutils/include/private/canned_fs_config.h"
+ }
+ ],
+ "qualified_types" :
+ [
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK13native_handle",
+ "name" : "const native_handle",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTIK13native_handle",
+ "size" : 12,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK22cutils_socket_buffer_t",
+ "name" : "const cutils_socket_buffer_t",
+ "referenced_type" : "_ZTI22cutils_socket_buffer_t",
+ "self_type" : "_ZTIK22cutils_socket_buffer_t",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK5iovec",
+ "name" : "const iovec",
+ "referenced_type" : "_ZTI5iovec",
+ "self_type" : "_ZTIK5iovec",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/klog.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKc",
+ "name" : "const char",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIKc",
+ "size" : 1,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ },
+ {
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKv",
+ "name" : "const void",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIKv",
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ }
+ ],
+ "record_types" :
+ [
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "version",
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "numFds",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "numInts",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "data",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIA0_i"
+ }
+ ],
+ "linker_set_key" : "_ZTI13native_handle",
+ "name" : "native_handle",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTI13native_handle",
+ "size" : 12,
+ "source_file" : "system/core/libcutils/include/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "data",
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "field_name" : "length",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "linker_set_key" : "_ZTI22cutils_socket_buffer_t",
+ "name" : "cutils_socket_buffer_t",
+ "referenced_type" : "_ZTI22cutils_socket_buffer_t",
+ "self_type" : "_ZTI22cutils_socket_buffer_t",
+ "size" : 8,
+ "source_file" : "system/core/libcutils/include/cutils/sockets.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "next",
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "field_name" : "first_child",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "field_name" : "last_child",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIP5cnode"
+ },
+ {
+ "field_name" : "name",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "field_name" : "value",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTI5cnode",
+ "name" : "cnode",
+ "referenced_type" : "_ZTI5cnode",
+ "self_type" : "_ZTI5cnode",
+ "size" : 20,
+ "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+ }
+ ],
+ "rvalue_reference_types" : []
+}
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index 3867f34..7f57637 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -89,6 +89,36 @@
#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
#endif
+/** Internal implementation detail. Do not use. */
+void atrace_begin_body(const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_end_body();
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_begin_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_end_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_for_track_end_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_instant_body(const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_instant_for_track_body(const char*, const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_int_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_int64_body(const char*, int64_t);
+
/**
* Opens the trace file for writing and reads the property for initial tags.
* The atrace.tags.enableflags property sets the tags to trace.
@@ -159,7 +189,6 @@
static inline void atrace_begin(uint64_t tag, const char* name)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_begin_body(const char*);
atrace_begin_body(name);
}
}
@@ -172,7 +201,6 @@
static inline void atrace_end(uint64_t tag)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_end_body();
atrace_end_body();
}
}
@@ -190,7 +218,6 @@
int32_t cookie)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_async_begin_body(const char*, int32_t);
atrace_async_begin_body(name, cookie);
}
}
@@ -203,7 +230,6 @@
static inline void atrace_async_end(uint64_t tag, const char* name, int32_t cookie)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_async_end_body(const char*, int32_t);
atrace_async_end_body(name, cookie);
}
}
@@ -221,7 +247,6 @@
static inline void atrace_async_for_track_begin(uint64_t tag, const char* track_name,
const char* name, int32_t cookie) {
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
atrace_async_for_track_begin_body(track_name, name, cookie);
}
}
@@ -235,7 +260,6 @@
static inline void atrace_async_for_track_end(uint64_t tag, const char* track_name,
int32_t cookie) {
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_async_for_track_end_body(const char*, int32_t);
atrace_async_for_track_end_body(track_name, cookie);
}
}
@@ -252,7 +276,6 @@
#define ATRACE_INSTANT(name) atrace_instant(ATRACE_TAG, name)
static inline void atrace_instant(uint64_t tag, const char* name) {
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_instant_body(const char*);
atrace_instant_body(name);
}
}
@@ -269,7 +292,6 @@
static inline void atrace_instant_for_track(uint64_t tag, const char* track_name,
const char* name) {
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_instant_for_track_body(const char*, const char*);
atrace_instant_for_track_body(track_name, name);
}
}
@@ -282,7 +304,6 @@
static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_int_body(const char*, int32_t);
atrace_int_body(name, value);
}
}
@@ -295,7 +316,6 @@
static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- void atrace_int64_body(const char*, int64_t);
atrace_int64_body(name, value);
}
}
diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp
index e9f58c3..2bf57eb 100644
--- a/libcutils/trace-host.cpp
+++ b/libcutils/trace-host.cpp
@@ -20,7 +20,6 @@
int atrace_marker_fd = -1;
uint64_t atrace_enabled_tags = 0;
-void atrace_set_debuggable(bool /*debuggable*/) {}
void atrace_set_tracing_enabled(bool /*enabled*/) {}
void atrace_update_tags() { }
void atrace_setup() { }
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 858b955..5023c79 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -230,7 +230,7 @@
}
std::vector<std::string> lines = android::base::Split(cfg_contents, "\n");
- for (const std::string line : lines) {
+ for (const auto& line : lines) {
if (line.empty() || line[0] == '#') {
continue;
}
@@ -421,7 +421,8 @@
}
if (strict && !module_loaded) {
- LOG(ERROR) << "LoadWithAliases was unable to load " << module_name;
+ LOG(ERROR) << "LoadWithAliases was unable to load " << module_name
+ << ", tried: " << android::base::Join(modules_to_load, ", ");
return false;
}
return true;
@@ -524,11 +525,8 @@
std::lock_guard guard(module_loaded_lock_);
// Remove loaded module form mod_with_deps and soft dependencies of other modules
- for (const auto& module_loaded : module_loaded_) {
- if (mod_with_deps.find(module_loaded) != mod_with_deps.end()) {
- mod_with_deps.erase(module_loaded);
- }
- }
+ for (const auto& module_loaded : module_loaded_)
+ mod_with_deps.erase(module_loaded);
// Remove loaded module form dependencies of other modules which are not loaded yet
for (const auto& module_loaded_path : module_loaded_paths_) {
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
index 94a1dc4..c4519e3 100644
--- a/libmodprobe/libmodprobe_ext.cpp
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -84,7 +84,7 @@
}
bool Modprobe::ModuleExists(const std::string& module_name) {
- struct stat fileStat;
+ struct stat fileStat {};
if (blocklist_enabled && module_blocklist_.count(module_name)) {
LOG(INFO) << "module " << module_name << " is blocklisted";
return false;
@@ -95,7 +95,7 @@
return false;
}
if (stat(deps.front().c_str(), &fileStat)) {
- LOG(INFO) << "module " << module_name << " does not exist";
+ PLOG(INFO) << "module " << module_name << " can't be loaded; can't access " << deps.front();
return false;
}
if (!S_ISREG(fileStat.st_mode)) {
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 5999e39..7cca105 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -362,14 +362,19 @@
return err->error;
}
+// Pass bitwise complement of prefix length to disable DAD, ie. use ~64 instead of 64.
// Returns zero on success and negative errno on failure.
int ifc_add_address(const char *name, const char *address, int prefixlen) {
- return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen, /*nodad*/ false);
+ bool nodad = (prefixlen < 0);
+ if (nodad) prefixlen = ~prefixlen;
+ return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen, nodad);
}
// Returns zero on success and negative errno on failure.
int ifc_del_address(const char *name, const char * address, int prefixlen) {
- return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen, /*nodad*/ false);
+ bool nodad = (prefixlen < 0);
+ if (nodad) prefixlen = ~prefixlen;
+ return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen, nodad);
}
/*
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 1f29040..06d386f 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -223,6 +223,13 @@
std::this_thread::sleep_for(5ms);
}
+ if (!ret && uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END) {
+ // Isolated UIDs are unlikely to be reused soon after removal,
+ // so free up the kernel resources for the UID level cgroup.
+ const auto uid_path = ConvertUidToPath(cgroup, uid);
+ ret = rmdir(uid_path.c_str());
+ }
+
return ret;
}
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 85a38f8..4609e6b 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -28,7 +28,6 @@
],
source_stem: "bindings",
bindgen_flags: [
- "--size_t-is-usize",
"--allowlist-function=AStatsEventList_addStatsEvent",
"--allowlist-function=AStatsEvent_.*",
"--allowlist-function=AStatsManager_.*",
diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp
index 819066e..c5c1934 100644
--- a/libstats/push_compat/Android.bp
+++ b/libstats/push_compat/Android.bp
@@ -26,7 +26,7 @@
cc_defaults {
name: "libstatspush_compat_defaults",
srcs: [
- "statsd_writer.c",
+ "statsd_writer.cpp",
"stats_event_list.c",
"StatsEventCompat.cpp"
],
diff --git a/libstats/push_compat/statsd_writer.c b/libstats/push_compat/statsd_writer.cpp
similarity index 97%
rename from libstats/push_compat/statsd_writer.c
rename to libstats/push_compat/statsd_writer.cpp
index 4818d11..a3600f3 100644
--- a/libstats/push_compat/statsd_writer.c
+++ b/libstats/push_compat/statsd_writer.cpp
@@ -15,9 +15,9 @@
*/
#include "statsd_writer.h"
+#include <android-base/threads.h>
#include <cutils/fs.h>
#include <cutils/sockets.h>
-#include <cutils/threads.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -108,7 +108,7 @@
case -ECONNREFUSED:
case -ENOENT:
i = atomic_exchange(&statsdLoggerWrite.sock, ret);
- /* FALLTHRU */
+ break;
default:
break;
}
@@ -188,7 +188,7 @@
* };
*/
- header.tid = gettid();
+ header.tid = android::base::GetThreadId();
header.realtime.tv_sec = ts->tv_sec;
header.realtime.tv_nsec = ts->tv_nsec;
@@ -272,7 +272,7 @@
if (ret < 0) {
ret = -errno;
}
- /* FALLTHRU */
+ break;
default:
break;
}
diff --git a/libstats/push_compat/statsd_writer.h b/libstats/push_compat/statsd_writer.h
index fe2d37c..f030b96 100644
--- a/libstats/push_compat/statsd_writer.h
+++ b/libstats/push_compat/statsd_writer.h
@@ -21,6 +21,8 @@
#include <stdatomic.h>
#include <sys/socket.h>
+__BEGIN_DECLS
+
/**
* Internal lock should not be exposed. This is bad design.
* TODO: rewrite it in c++ code and encapsulate the functionality in a
@@ -42,4 +44,6 @@
void (*noteDrop)(int error, int tag);
};
+__END_DECLS
+
#endif // ANDROID_STATS_LOG_STATS_WRITER_H
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index cd9db54..55bbe46 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -150,15 +150,10 @@
}
NetlinkEvent::~NetlinkEvent() {
- int i;
- if (mPath)
- free(mPath);
- if (mSubsystem)
- free(mSubsystem);
- for (i = 0; i < NL_PARAMS_MAX; i++) {
- if (!mParams[i])
- break;
- free(mParams[i]);
+ free(mPath);
+ free(mSubsystem);
+ for (auto param : mParams) {
+ free(param);
}
}
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index 3ffcf7e..364a177 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -280,158 +280,181 @@
: 0);
}
+// is_any_surrogate() returns true if w is either a high or low surrogate
+static constexpr bool is_any_surrogate(char16_t w) {
+ return (w & 0xf800) == 0xd800;
+}
+
+// is_surrogate_pair() returns true if w1 and w2 form a valid surrogate pair
+static constexpr bool is_surrogate_pair(char16_t w1, char16_t w2) {
+ return ((w1 & 0xfc00) == 0xd800) && ((w2 & 0xfc00) == 0xdc00);
+}
+
+// TODO: currently utf16_to_utf8_length() returns -1 if src_len == 0,
+// which is inconsistent with utf8_to_utf16_length(), here we keep the
+// current behavior as intended not to break compatibility
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len)
+{
+ if (src == nullptr || src_len == 0)
+ return -1;
+
+ const char16_t* const end = src + src_len;
+ const char16_t* in = src;
+ size_t utf8_len = 0;
+
+ while (in < end) {
+ char16_t w = *in++;
+ if (LIKELY(w < 0x0080)) {
+ utf8_len += 1;
+ continue;
+ }
+ if (LIKELY(w < 0x0800)) {
+ utf8_len += 2;
+ continue;
+ }
+ if (LIKELY(!is_any_surrogate(w))) {
+ utf8_len += 3;
+ continue;
+ }
+ if (in < end && is_surrogate_pair(w, *in)) {
+ utf8_len += 4;
+ in++;
+ continue;
+ }
+ /* skip if at the end of the string or invalid surrogate pair */
+ }
+ return (in == end && utf8_len < SSIZE_MAX) ? utf8_len : -1;
+}
+
void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len)
{
if (src == nullptr || src_len == 0 || dst == nullptr) {
return;
}
- const char16_t* cur_utf16 = src;
- const char16_t* const end_utf16 = src + src_len;
- char *cur = dst;
- while (cur_utf16 < end_utf16) {
- char32_t utf32;
- // surrogate pairs
- if((*cur_utf16 & 0xFC00) == 0xD800 && (cur_utf16 + 1) < end_utf16
- && (*(cur_utf16 + 1) & 0xFC00) == 0xDC00) {
- utf32 = (*cur_utf16++ - 0xD800) << 10;
- utf32 |= *cur_utf16++ - 0xDC00;
- utf32 += 0x10000;
- } else {
- utf32 = (char32_t) *cur_utf16++;
+ const char16_t* in = src;
+ const char16_t* const in_end = src + src_len;
+ char* out = dst;
+ const char* const out_end = dst + dst_len;
+ char16_t w2;
+
+ auto err_out = [&out, &out_end, &dst_len]() {
+ LOG_ALWAYS_FATAL_IF(out >= out_end,
+ "target utf8 string size %zu too short", dst_len);
+ };
+
+ while (in < in_end) {
+ char16_t w = *in++;
+ if (LIKELY(w < 0x0080)) {
+ if (out + 1 > out_end)
+ return err_out();
+ *out++ = (char)(w & 0xff);
+ continue;
}
- const size_t len = utf32_codepoint_utf8_length(utf32);
- LOG_ALWAYS_FATAL_IF(dst_len < len, "%zu < %zu", dst_len, len);
- utf32_codepoint_to_utf8((uint8_t*)cur, utf32, len);
- cur += len;
- dst_len -= len;
+ if (LIKELY(w < 0x0800)) {
+ if (out + 2 > out_end)
+ return err_out();
+ *out++ = (char)(0xc0 | ((w >> 6) & 0x1f));
+ *out++ = (char)(0x80 | ((w >> 0) & 0x3f));
+ continue;
+ }
+ if (LIKELY(!is_any_surrogate(w))) {
+ if (out + 3 > out_end)
+ return err_out();
+ *out++ = (char)(0xe0 | ((w >> 12) & 0xf));
+ *out++ = (char)(0x80 | ((w >> 6) & 0x3f));
+ *out++ = (char)(0x80 | ((w >> 0) & 0x3f));
+ continue;
+ }
+ /* surrogate pair */
+ if (in < in_end && (w2 = *in, is_surrogate_pair(w, w2))) {
+ if (out + 4 > out_end)
+ return err_out();
+ char32_t dw = (char32_t)(0x10000 + ((w - 0xd800) << 10) + (w2 - 0xdc00));
+ *out++ = (char)(0xf0 | ((dw >> 18) & 0x07));
+ *out++ = (char)(0x80 | ((dw >> 12) & 0x3f));
+ *out++ = (char)(0x80 | ((dw >> 6) & 0x3f));
+ *out++ = (char)(0x80 | ((dw >> 0) & 0x3f));
+ in++;
+ }
+ /* We reach here in two cases:
+ * 1) (in == in_end), which means end of the input string
+ * 2) (w2 & 0xfc00) != 0xdc00, which means invalid surrogate pair
+ * In either case, we intentionally do nothing and skip
+ */
}
- LOG_ALWAYS_FATAL_IF(dst_len < 1, "%zu < 1", dst_len);
- *cur = '\0';
+ *out = '\0';
+ return;
}
// --------------------------------------------------------------------------
// UTF-8
// --------------------------------------------------------------------------
-ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len)
-{
- if (src == nullptr || src_len == 0) {
- return -1;
- }
-
- size_t ret = 0;
- const char16_t* const end = src + src_len;
- while (src < end) {
- size_t char_len;
- if ((*src & 0xFC00) == 0xD800 && (src + 1) < end
- && (*(src + 1) & 0xFC00) == 0xDC00) {
- // surrogate pairs are always 4 bytes.
- char_len = 4;
- src += 2;
- } else {
- char_len = utf32_codepoint_utf8_length((char32_t)*src++);
- }
- if (SSIZE_MAX - char_len < ret) {
- // If this happens, we would overflow the ssize_t type when
- // returning from this function, so we cannot express how
- // long this string is in an ssize_t.
- android_errorWriteLog(0x534e4554, "37723026");
- return -1;
- }
- ret += char_len;
- }
- return ret;
+static char32_t utf8_4b_to_utf32(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4) {
+ return ((c1 & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f);
}
-/**
- * Returns 1-4 based on the number of leading bits.
- *
- * 1111 -> 4
- * 1110 -> 3
- * 110x -> 2
- * 10xx -> 1
- * 0xxx -> 1
- */
-static inline size_t utf8_codepoint_len(uint8_t ch)
-{
- return ((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1;
-}
-
-static inline void utf8_shift_and_mask(uint32_t* codePoint, const uint8_t byte)
-{
- *codePoint <<= 6;
- *codePoint |= 0x3F & byte;
-}
-
-static inline uint32_t utf8_to_utf32_codepoint(const uint8_t *src, size_t length)
-{
- uint32_t unicode;
-
- switch (length)
- {
- case 1:
- return src[0];
- case 2:
- unicode = src[0] & 0x1f;
- utf8_shift_and_mask(&unicode, src[1]);
- return unicode;
- case 3:
- unicode = src[0] & 0x0f;
- utf8_shift_and_mask(&unicode, src[1]);
- utf8_shift_and_mask(&unicode, src[2]);
- return unicode;
- case 4:
- unicode = src[0] & 0x07;
- utf8_shift_and_mask(&unicode, src[1]);
- utf8_shift_and_mask(&unicode, src[2]);
- utf8_shift_and_mask(&unicode, src[3]);
- return unicode;
- default:
- return 0xffff;
- }
-
- //printf("Char at %p: len=%d, utf-16=%p\n", src, length, (void*)result);
-}
+// TODO: current behavior of converting UTF8 to UTF-16 has a few issues below
+//
+// 1. invalid trailing bytes (i.e. not b'10xxxxxx) are treated as valid trailing
+// bytes and follows normal conversion rules
+// 2. invalid leading byte (b'10xxxxxx) is treated as a valid single UTF-8 byte
+// 3. invalid leading byte (b'11111xxx) is treated as a valid leading byte
+// (same as b'11110xxx) for a 4-byte UTF-8 sequence
+// 4. an invalid 4-byte UTF-8 sequence that translates to a codepoint < U+10000
+// will be converted as a valid UTF-16 character
+//
+// We keep the current behavior as is but with warnings logged, so as not to
+// break compatibility. However, this needs to be addressed later.
ssize_t utf8_to_utf16_length(const uint8_t* u8str, size_t u8len, bool overreadIsFatal)
{
- const uint8_t* const u8end = u8str + u8len;
- const uint8_t* u8cur = u8str;
-
- /* Validate that the UTF-8 is the correct len */
- size_t u16measuredLen = 0;
- while (u8cur < u8end) {
- u16measuredLen++;
- int u8charLen = utf8_codepoint_len(*u8cur);
- // Malformed utf8, some characters are beyond the end.
- // Cases:
- // If u8charLen == 1, this becomes u8cur >= u8end, which cannot happen as u8cur < u8end,
- // then this condition fail and we continue, as expected.
- // If u8charLen == 2, this becomes u8cur + 1 >= u8end, which fails only if
- // u8cur == u8end - 1, that is, there was only one remaining character to read but we need
- // 2 of them. This condition holds and we return -1, as expected.
- if (u8cur + u8charLen - 1 >= u8end) {
- if (overreadIsFatal) {
- LOG_ALWAYS_FATAL("Attempt to overread computing length of utf8 string");
- } else {
- return -1;
- }
- }
- uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8charLen);
- if (codepoint > 0xFFFF) u16measuredLen++; // this will be a surrogate pair in utf16
- u8cur += u8charLen;
- }
-
- /**
- * Make sure that we ended where we thought we would and the output UTF-16
- * will be exactly how long we were told it would be.
- */
- if (u8cur != u8end) {
+ if (u8str == nullptr)
return -1;
- }
- return u16measuredLen;
+ const uint8_t* const in_end = u8str + u8len;
+ const uint8_t* in = u8str;
+ size_t utf16_len = 0;
+
+ while (in < in_end) {
+ uint8_t c = *in;
+ utf16_len++;
+ if (LIKELY((c & 0x80) == 0)) {
+ in++;
+ continue;
+ }
+ if (UNLIKELY(c < 0xc0)) {
+ ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+ in++;
+ continue;
+ }
+ if (LIKELY(c < 0xe0)) {
+ in += 2;
+ continue;
+ }
+ if (LIKELY(c < 0xf0)) {
+ in += 3;
+ continue;
+ } else {
+ uint8_t c2, c3, c4;
+ if (UNLIKELY(c >= 0xf8)) {
+ ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+ }
+ c2 = in[1]; c3 = in[2]; c4 = in[3];
+ if (utf8_4b_to_utf32(c, c2, c3, c4) >= 0x10000) {
+ utf16_len++;
+ }
+ in += 4;
+ continue;
+ }
+ }
+ if (in == in_end) {
+ return utf16_len < SSIZE_MAX ? utf16_len : -1;
+ }
+ if (overreadIsFatal)
+ LOG_ALWAYS_FATAL("Attempt to overread computing length of utf8 string");
+ return -1;
}
char16_t* utf8_to_utf16(const uint8_t* u8str, size_t u8len, char16_t* u16str, size_t u16len) {
@@ -444,38 +467,75 @@
char16_t* utf8_to_utf16_no_null_terminator(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen) {
- if (dstLen == 0) {
+ if (src == nullptr || srcLen == 0 || dstLen == 0) {
return dst;
}
// A value > SSIZE_MAX is probably a negative value returned as an error and casted.
LOG_ALWAYS_FATAL_IF(dstLen > SSIZE_MAX, "dstLen is %zu", dstLen);
- const uint8_t* const u8end = src + srcLen;
- const uint8_t* u8cur = src;
- const char16_t* const u16end = dst + dstLen;
- char16_t* u16cur = dst;
- while (u8cur < u8end && u16cur < u16end) {
- size_t u8len = utf8_codepoint_len(*u8cur);
- uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8len);
+ const uint8_t* const in_end = src + srcLen;
+ const uint8_t* in = src;
+ const char16_t* const out_end = dst + dstLen;
+ char16_t* out = dst;
+ uint8_t c, c2, c3, c4;
+ char32_t w;
- // Convert the UTF32 codepoint to one or more UTF16 codepoints
- if (codepoint <= 0xFFFF) {
- // Single UTF16 character
- *u16cur++ = (char16_t) codepoint;
- } else {
- // Multiple UTF16 characters with surrogates
- codepoint = codepoint - 0x10000;
- *u16cur++ = (char16_t) ((codepoint >> 10) + 0xD800);
- if (u16cur >= u16end) {
- // Ooops... not enough room for this surrogate pair.
- return u16cur-1;
- }
- *u16cur++ = (char16_t) ((codepoint & 0x3FF) + 0xDC00);
+ auto err_in = [&c, &out]() {
+ ALOGW("Unended UTF-8 byte: 0x%02x", c);
+ return out;
+ };
+
+ while (in < in_end && out < out_end) {
+ c = *in++;
+ if (LIKELY((c & 0x80) == 0)) {
+ *out++ = (char16_t)(c);
+ continue;
}
-
- u8cur += u8len;
+ if (UNLIKELY(c < 0xc0)) {
+ ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+ *out++ = (char16_t)(c);
+ continue;
+ }
+ if (LIKELY(c < 0xe0)) {
+ if (UNLIKELY(in + 1 > in_end)) {
+ return err_in();
+ }
+ c2 = *in++;
+ *out++ = (char16_t)(((c & 0x1f) << 6) | (c2 & 0x3f));
+ continue;
+ }
+ if (LIKELY(c < 0xf0)) {
+ if (UNLIKELY(in + 2 > in_end)) {
+ return err_in();
+ }
+ c2 = *in++; c3 = *in++;
+ *out++ = (char16_t)(((c & 0x0f) << 12) |
+ ((c2 & 0x3f) << 6) | (c3 & 0x3f));
+ continue;
+ } else {
+ if (UNLIKELY(in + 3 > in_end)) {
+ return err_in();
+ }
+ if (UNLIKELY(c >= 0xf8)) {
+ ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
+ }
+ // Multiple UTF16 characters with surrogates
+ c2 = *in++; c3 = *in++; c4 = *in++;
+ w = utf8_4b_to_utf32(c, c2, c3, c4);
+ if (UNLIKELY(w < 0x10000)) {
+ *out++ = (char16_t)(w);
+ } else {
+ if (UNLIKELY(out + 2 > out_end)) {
+ // Ooops.... not enough room for this surrogate pair.
+ return out;
+ }
+ *out++ = (char16_t)(((w - 0x10000) >> 10) + 0xd800);
+ *out++ = (char16_t)(((w - 0x10000) & 0x3ff) + 0xdc00);
+ }
+ continue;
+ }
}
- return u16cur;
+ return out;
}
}
diff --git a/libutils/Vector_fuzz.cpp b/libutils/Vector_fuzz.cpp
index f6df051..6fd2baf 100644
--- a/libutils/Vector_fuzz.cpp
+++ b/libutils/Vector_fuzz.cpp
@@ -13,71 +13,203 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "fuzzer/FuzzedDataProvider.h"
-#include "utils/Vector.h"
-static constexpr uint16_t MAX_VEC_SIZE = 5000;
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
-void runVectorFuzz(const uint8_t* data, size_t size) {
- FuzzedDataProvider dataProvider(data, size);
- android::Vector<uint8_t> vec = android::Vector<uint8_t>();
- // We want to test handling of sizeof as well.
- android::Vector<uint32_t> vec32 = android::Vector<uint32_t>();
+#include <functional>
- // We're going to generate two vectors of this size
- size_t vectorSize = dataProvider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
- vec.setCapacity(vectorSize);
- vec32.setCapacity(vectorSize);
- for (size_t i = 0; i < vectorSize; i++) {
- uint8_t count = dataProvider.ConsumeIntegralInRange<uint8_t>(1, 5);
- vec.insertAt((uint8_t)i, i, count);
- vec32.insertAt((uint32_t)i, i, count);
- vec.push_front(i);
- vec32.push(i);
+using android::Vector;
+
+static constexpr uint16_t MAX_VEC_SIZE = 100;
+static constexpr bool kLog = false;
+
+struct NonTrivialDestructor {
+ NonTrivialDestructor() : mInit(1) {}
+ ~NonTrivialDestructor() {
+ LOG_ALWAYS_FATAL_IF(mInit != 1, "mInit should be 1, but it's: %d", mInit);
+ mInit--;
+ LOG_ALWAYS_FATAL_IF(mInit != 0, "mInit should be 0, but it's: %d", mInit);
}
- // Now we'll perform some test operations with any remaining data
- // Index to perform operations at
- size_t index = dataProvider.ConsumeIntegralInRange<size_t>(0, vec.size());
- std::vector<uint8_t> remainingVec = dataProvider.ConsumeRemainingBytes<uint8_t>();
- // Insert an array and vector
- vec.insertArrayAt(remainingVec.data(), index, remainingVec.size());
- android::Vector<uint8_t> vecCopy = android::Vector<uint8_t>(vec);
- vec.insertVectorAt(vecCopy, index);
- // Same thing for 32 bit vector
- android::Vector<uint32_t> vec32Copy = android::Vector<uint32_t>(vec32);
- vec32.insertArrayAt(vec32Copy.array(), index, vec32.size());
- vec32.insertVectorAt(vec32Copy, index);
- // Replace single character
- if (remainingVec.size() > 0) {
- vec.replaceAt(remainingVec[0], index);
- vec32.replaceAt(static_cast<uint32_t>(remainingVec[0]), index);
- } else {
- vec.replaceAt(0, index);
- vec32.replaceAt(0, index);
+ private:
+ uint8_t mInit;
+};
+
+template <typename T>
+struct VectorFuzzerData {
+ Vector<T> vector;
+ const std::vector<std::function<void(FuzzedDataProvider&, Vector<T>&)>> funcs = {
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ // operator= Vector<TYPE>, still needs for SortedVector
+ if (kLog) ALOGI("operator=");
+ vector = testVector(provider);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("clear");
+ vector.clear();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("size");
+ vector.size();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("isEmpty");
+ vector.isEmpty();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("capacity");
+ vector.capacity();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+ if (kLog) ALOGI("setCapacity");
+ vector.setCapacity(vectorSize);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+ if (kLog) ALOGI("resize");
+ vector.resize(vectorSize);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("array");
+ vector.array();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("editArray");
+ vector.editArray();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ if (vector.size() == 0) return;
+ size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+ if (kLog) ALOGI("operator[]");
+ vector[idx]; // returns a const value for Vector
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ if (vector.size() == 0) return;
+ size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+ if (kLog) ALOGI("itemAt");
+ vector.itemAt(idx);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (vector.size() == 0) return;
+ if (kLog) ALOGI("top");
+ vector.top();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ if (vector.size() == 0) return;
+ size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+ if (kLog) ALOGI("editItemAt");
+ vector.editItemAt(idx);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (vector.size() == 0) return;
+ if (kLog) ALOGI("editTop");
+ vector.editTop() = T{};
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+ Vector vec2 = testVector(provider);
+ if (vec2.size() == 0) return; // TODO: maybe we should support this?
+ if (kLog) ALOGI("insertVectorAt %d of size %zu", idx, vec2.size());
+ vector.insertVectorAt(vec2, idx);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ if (kLog) ALOGI("appendVector");
+ vector.appendVector(testVector(provider));
+ },
+ // TODO: insertArrayAt
+ // TODO: appendArray
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+ uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
+ if (kLog) ALOGI("insertAt");
+ vector.insertAt(idx, numItems);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+ uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
+ if (kLog) ALOGI("insertAt");
+ vector.insertAt(T{}, idx, numItems);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (vector.size() == 0) return;
+ if (kLog) ALOGI("pop");
+ vector.pop();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("push");
+ vector.push();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("add");
+ vector.add();
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("add");
+ vector.add(T{});
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+ if (kLog) ALOGI("replaceAt");
+ vector.replaceAt(idx);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+ if (kLog) ALOGI("replaceAt");
+ vector.replaceAt(T{}, idx);
+ },
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ if (vector.size() == 0) return;
+ uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+ if (kLog) ALOGI("remoteItemsAt");
+ vector.removeItemsAt(idx); // TODO: different count
+ },
+ // removeAt is alias for removeItemsAt
+ // TODO: sort
+ [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+ (void)provider;
+ if (kLog) ALOGI("getItemSize");
+ vector.getItemSize();
+ },
+ // TODO: iterators
+ };
+
+ Vector<T> testVector(FuzzedDataProvider& provider) {
+ Vector<T> vec;
+ size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+ return vec;
}
- // Add any remaining bytes
- for (uint8_t i : remainingVec) {
- vec.add(i);
- vec32.add(static_cast<uint32_t>(i));
+
+ void fuzz(FuzzedDataProvider&& provider) {
+ while (provider.remaining_bytes()) {
+ size_t funcIdx = provider.ConsumeIntegralInRange<size_t>(0, funcs.size() - 1);
+ funcs[funcIdx](provider, vector);
+ }
}
- // Shrink capactiy
- vec.setCapacity(remainingVec.size());
- vec32.setCapacity(remainingVec.size());
- // Iterate through each pointer
- size_t sum = 0;
- for (auto& it : vec) {
- sum += it;
- }
- for (auto& it : vec32) {
- sum += it;
- }
- // Cleanup
- vec.clear();
- vecCopy.clear();
- vec32.clear();
- vec32Copy.clear();
-}
+};
+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- runVectorFuzz(data, size);
+ FuzzedDataProvider provider(data, size);
+
+ provider.PickValueInArray<std::function<void()>>({
+ [&]() { VectorFuzzerData<uint8_t>().fuzz(std::move(provider)); },
+ [&]() { VectorFuzzerData<int32_t>().fuzz(std::move(provider)); },
+ [&]() { VectorFuzzerData<NonTrivialDestructor>().fuzz(std::move(provider)); },
+ })();
+
return 0;
}
diff --git a/libutils/include/utils/Vector.h b/libutils/include/utils/Vector.h
index be35ea2..d5db3cb 100644
--- a/libutils/include/utils/Vector.h
+++ b/libutils/include/utils/Vector.h
@@ -67,13 +67,10 @@
virtual ~Vector();
/*! copy operator */
- const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
- Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
+ Vector<TYPE>& operator=(const Vector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
+ Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
- const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
- Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
-
- /*
+ /*
* empty the vector
*/
@@ -248,27 +245,18 @@
finish_vector();
}
-template<class TYPE> inline
-Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
- VectorImpl::operator = (rhs);
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
+{
+ VectorImpl::operator=(rhs);
return *this;
}
-template<class TYPE> inline
-const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
- VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
- return *this;
-}
-
-template<class TYPE> inline
-Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
- VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
- return *this;
-}
-
-template<class TYPE> inline
-const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
- VectorImpl::operator = (rhs);
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(
+ const SortedVector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
+{
+ VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
return *this;
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5344368..d2499ef 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -533,7 +533,7 @@
# Should be before netd, but after apex, properties and logging is available.
trigger load_bpf_programs
- # Now we can start zygote for devices with file based encryption
+ # Now we can start zygote.
trigger zygote-start
# Remove a file to wake up anything waiting for firmware.
@@ -604,8 +604,8 @@
chmod 0700 /metadata/vold
mkdir /metadata/password_slots 0771 root system
mkdir /metadata/bootstat 0750 system log
- mkdir /metadata/ota 0700 root system
- mkdir /metadata/ota/snapshots 0700 root system
+ mkdir /metadata/ota 0750 root system
+ mkdir /metadata/ota/snapshots 0750 root system
mkdir /metadata/userspacereboot 0770 root system
mkdir /metadata/watchdog 0770 root system
@@ -1021,13 +1021,9 @@
# Must start after 'derive_classpath' to have *CLASSPATH variables set.
start odsign
- # Before we can lock keys and proceed to the next boot stage, wait for
- # odsign to be done with the key
+ # Wait for odsign to be done with the key.
wait_for_prop odsign.key.done 1
- # Lock the fs-verity keyring, so no more keys can be added
- exec -- /system/bin/fsverity_init --lock
-
# Bump the boot level to 1000000000; this prevents further on-device signing.
# This is a special value that shuts down the thread which listens for
# further updates.
@@ -1056,28 +1052,10 @@
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
-on zygote-start && property:ro.crypto.state=unencrypted
+on zygote-start
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
- exec_start update_verifier_nonencrypted
- start statsd
- start netd
- start zygote
- start zygote_secondary
-
-on zygote-start && property:ro.crypto.state=unsupported
- wait_for_prop odsign.verification.done 1
- # A/B update verifier that marks a successful boot.
- exec_start update_verifier_nonencrypted
- start statsd
- start netd
- start zygote
- start zygote_secondary
-
-on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
- wait_for_prop odsign.verification.done 1
- # A/B update verifier that marks a successful boot.
- exec_start update_verifier_nonencrypted
+ exec_start update_verifier
start statsd
start netd
start zygote
@@ -1129,7 +1107,7 @@
write /dev/sys/fs/by-name/userdata/iostat_enable 1
# set readahead multiplier for POSIX_FADV_SEQUENTIAL files
- write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16
+ write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 128
# limit discard size to 128MB in order to avoid long IO latency
# for filesystem tuning first (dm or sda)