Merge "[Trusty][Metrics] Update struct to add is_crash on the NS side" into main
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 3a882ea..0c5543e 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -452,6 +452,7 @@
header_libs: [
"bionic_libc_platform_headers",
+ "libnative_bridge_support_accessor_headers",
],
static_libs: [
@@ -461,6 +462,8 @@
"libtombstone_proto",
"libprotobuf-cpp-lite",
+
+ "libnative_bridge_guest_state_accessor",
],
shared_libs: [
@@ -476,6 +479,15 @@
// Required for tests.
required: ["crash_dump.policy"],
+
+ target: {
+ android: {
+ header_libs: [
+ "libnative_bridge_support_accessor_headers", // For dlext_namespaces.h
+ ],
+ shared_libs: ["libdl_android"], // For android_get_exported_namespace implementation
+ },
+ },
}
cc_binary {
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 203b485..1c1fb8a 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -25,6 +25,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <cstdint>
#include <limits>
#include <map>
#include <memory>
@@ -42,6 +43,7 @@
#include <android-base/unique_fd.h>
#include <bionic/macros.h>
#include <bionic/reserved_signals.h>
+#include <bionic/tls_defines.h>
#include <cutils/sockets.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -52,7 +54,18 @@
#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Error.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineRiscv64.h>
#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsRiscv64.h>
+#include <unwindstack/UserArm.h>
+#include <unwindstack/UserArm64.h>
+#include <unwindstack/UserRiscv64.h>
+
+#include <native_bridge_support/guest_state_accessor/accessor.h>
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/tombstone.h"
@@ -68,6 +81,10 @@
using android::base::StringPrintf;
using android::base::unique_fd;
+// This stores guest architecture. When the architecture is supported, tombstone file will output
+// guest state information.
+static Architecture g_guest_arch;
+
static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
struct stat st;
std::string task_path = StringPrintf("task/%d", tid);
@@ -286,28 +303,27 @@
*recoverable_crash = false;
if (rc == -1) {
PLOG(FATAL) << "failed to read target ucontext";
- } else {
- ssize_t expected_size = 0;
- switch (crash_info->header.version) {
- case 1:
- case 2:
- case 3:
- expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
- break;
+ }
+ ssize_t expected_size = 0;
+ switch (crash_info->header.version) {
+ case 1:
+ case 2:
+ case 3:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
+ break;
- case 4:
- expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
- break;
+ case 4:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
+ break;
- default:
- LOG(FATAL) << "unexpected CrashInfo version: " << crash_info->header.version;
- break;
- };
+ default:
+ LOG(FATAL) << "unexpected CrashInfo version: " << crash_info->header.version;
+ break;
+ }
- if (rc < expected_size) {
- LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
- << expected_size;
- }
+ if (rc < expected_size) {
+ LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
+ << expected_size;
}
switch (crash_info->header.version) {
@@ -403,6 +419,116 @@
sigaction(SIGPIPE, &action, nullptr);
}
+static bool PtracePeek(int request, pid_t tid, uintptr_t addr, void* data, std::string_view err_msg,
+ uintptr_t* result) {
+ errno = 0;
+ *result = ptrace(request, tid, addr, data);
+ if (errno != 0) {
+ PLOG(ERROR) << err_msg;
+ return false;
+ }
+ return true;
+}
+
+static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
+ NativeBridgeGuestRegs* guest_regs) {
+ auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(tid);
+
+ uintptr_t header_ptr = 0;
+ uintptr_t base = 0;
+#if defined(__x86_64__)
+ if (!PtracePeek(PTRACE_PEEKUSER, tid, offsetof(user_regs_struct, fs_base), nullptr,
+ "failed to read thread register for thread " + std::to_string(tid), &base)) {
+ return false;
+ }
+#elif defined(__aarch64__)
+ // base is implicitly casted to uint64_t.
+ struct iovec pt_iov {
+ .iov_base = &base, .iov_len = sizeof(base),
+ };
+
+ if (ptrace(PTRACE_GETREGSET, tid, NT_ARM_TLS, &pt_iov) != 0) {
+ PLOG(ERROR) << "failed to read thread register for thread " << tid;
+ return false;
+ }
+#elif defined(__riscv)
+ struct user_regs_struct regs;
+ struct iovec pt_iov = {.iov_base = ®s, .iov_len = sizeof(regs)};
+ if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &pt_iov) != 0) {
+ PLOG(ERROR) << "failed to read thread register for thread " << tid;
+ return false;
+ }
+ base = reinterpret_cast<uintptr_t>(regs.tp);
+#else
+ // TODO(b/339287219): Add case for Riscv host.
+ return false;
+#endif
+ auto ptr_to_guest_slot = base + TLS_SLOT_NATIVE_BRIDGE_GUEST_STATE * sizeof(uintptr_t);
+ if (!process_memory->ReadFully(ptr_to_guest_slot, &header_ptr, sizeof(uintptr_t))) {
+ PLOG(ERROR) << "failed to get guest state TLS slot content for thread " << tid;
+ return false;
+ }
+
+ NativeBridgeGuestStateHeader header;
+ if (!process_memory->ReadFully(header_ptr, &header, sizeof(NativeBridgeGuestStateHeader))) {
+ PLOG(ERROR) << "failed to get the guest state header for thread " << tid;
+ return false;
+ }
+ if (header.signature != NATIVE_BRIDGE_GUEST_STATE_SIGNATURE) {
+ // Return when ptr points to unmapped memory or no valid guest state.
+ return false;
+ }
+ auto guest_state_data_copy = std::make_unique<unsigned char[]>(header.guest_state_data_size);
+ if (!process_memory->ReadFully(reinterpret_cast<uintptr_t>(header.guest_state_data),
+ guest_state_data_copy.get(), header.guest_state_data_size)) {
+ PLOG(ERROR) << "failed to read the guest state data for thread " << tid;
+ return false;
+ }
+
+ LoadGuestStateRegisters(guest_state_data_copy.get(), header.guest_state_data_size, guest_regs);
+ return true;
+}
+
+static void ReadGuestRegisters([[maybe_unused]] std::unique_ptr<unwindstack::Regs>* regs,
+ pid_t tid) {
+ // TODO: remove [[maybe_unused]], when the ARM32 case is removed from the native bridge support.
+ NativeBridgeGuestRegs guest_regs;
+ if (!GetGuestRegistersFromCrashedProcess(tid, &guest_regs)) {
+ return;
+ }
+
+ switch (guest_regs.guest_arch) {
+#if defined(__LP64__)
+ case NATIVE_BRIDGE_ARCH_ARM64: {
+ unwindstack::arm64_user_regs arm64_user_regs = {};
+ for (size_t i = 0; i < unwindstack::ARM64_REG_R31; i++) {
+ arm64_user_regs.regs[i] = guest_regs.regs_arm64.x[i];
+ }
+ arm64_user_regs.sp = guest_regs.regs_arm64.sp;
+ arm64_user_regs.pc = guest_regs.regs_arm64.ip;
+ regs->reset(unwindstack::RegsArm64::Read(&arm64_user_regs));
+
+ g_guest_arch = Architecture::ARM64;
+ break;
+ }
+ case NATIVE_BRIDGE_ARCH_RISCV64: {
+ unwindstack::riscv64_user_regs riscv64_user_regs = {};
+ // RISCV64_REG_PC is at the first position.
+ riscv64_user_regs.regs[0] = guest_regs.regs_riscv64.ip;
+ for (size_t i = 1; i < unwindstack::RISCV64_REG_REAL_COUNT; i++) {
+ riscv64_user_regs.regs[i] = guest_regs.regs_riscv64.x[i];
+ }
+ regs->reset(unwindstack::RegsRiscv64::Read(&riscv64_user_regs, tid));
+
+ g_guest_arch = Architecture::RISCV64;
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+}
+
int main(int argc, char** argv) {
DefuseSignalHandlers();
InstallSigPipeHandler();
@@ -551,6 +677,7 @@
continue;
}
}
+ ReadGuestRegisters(&info.guest_registers, thread);
thread_info[thread] = std::move(info);
}
@@ -660,8 +787,32 @@
{
ATRACE_NAME("engrave_tombstone");
- engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
- g_target_thread, process_info, &open_files, &amfd_data);
+ unwindstack::ArchEnum regs_arch = unwindstack::ARCH_UNKNOWN;
+ switch (g_guest_arch) {
+ case Architecture::ARM32: {
+ regs_arch = unwindstack::ARCH_ARM;
+ break;
+ }
+ case Architecture::ARM64: {
+ regs_arch = unwindstack::ARCH_ARM64;
+ break;
+ }
+ case Architecture::RISCV64: {
+ regs_arch = unwindstack::ARCH_RISCV64;
+ break;
+ }
+ default: {
+ }
+ }
+ if (regs_arch == unwindstack::ARCH_UNKNOWN) {
+ engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
+ g_target_thread, process_info, &open_files, &amfd_data);
+ } else {
+ unwindstack::AndroidRemoteUnwinder guest_unwinder(vm_pid, regs_arch);
+ engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
+ g_target_thread, process_info, &open_files, &amfd_data, &g_guest_arch,
+ &guest_unwinder);
+ }
}
}
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 3b52776..05143ed 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -202,7 +202,9 @@
fprintf(stderr, " fdsan_file close a file descriptor that's owned by a FILE*\n");
fprintf(stderr, " fdsan_dir close a file descriptor that's owned by a DIR*\n");
fprintf(stderr, " seccomp fail a seccomp check\n");
+#if defined(__LP64__)
fprintf(stderr, " xom read execute-only memory\n");
+#endif
fprintf(stderr, "\n");
fprintf(stderr, " LOG_ALWAYS_FATAL call liblog LOG_ALWAYS_FATAL\n");
fprintf(stderr, " LOG_ALWAYS_FATAL_IF call liblog LOG_ALWAYS_FATAL_IF\n");
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index be999e0..dfdfabd 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
@@ -28,6 +28,7 @@
#include <android-base/unique_fd.h>
#include "open_files_list.h"
+#include "tombstone.pb.h"
#include "types.h"
// Forward declarations
@@ -54,14 +55,17 @@
unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
- std::string* amfd_data);
+ std::string* amfd_data, const Architecture* guest_arch = nullptr,
+ unwindstack::AndroidUnwinder* guest_unwinder = nullptr);
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
siginfo_t* siginfo, ucontext_t* ucontext);
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
- const ProcessInfo& process_info, const OpenFilesList* open_files);
+ const ProcessInfo& process_info, const OpenFilesList* open_files,
+ const Architecture* guest_arch,
+ unwindstack::AndroidUnwinder* guest_unwinder);
bool tombstone_proto_to_text(
const Tombstone& tombstone,
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index 4d69658..c799f24 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -39,6 +39,8 @@
int signo = 0;
siginfo_t* siginfo = nullptr;
+
+ std::unique_ptr<unwindstack::Regs> guest_registers;
};
// This struct is written into a pipe from inside the crashing process.
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 5a416d6..0ce5573 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -125,10 +125,12 @@
unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
- std::string* amfd_data) {
+ std::string* amfd_data, const Architecture* guest_arch,
+ unwindstack::AndroidUnwinder* guest_unwinder) {
// Don't copy log messages to tombstone unless this is a development device.
Tombstone tombstone;
- engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files);
+ engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files,
+ guest_arch, guest_unwinder);
if (proto_fd != -1) {
if (!tombstone.SerializeToFileDescriptor(proto_fd.get())) {
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 5546b7b..3e8ab6e 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -482,7 +482,8 @@
}
static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
- const ThreadInfo& thread_info, bool memory_dump = false) {
+ const ThreadInfo& thread_info, bool memory_dump = false,
+ unwindstack::AndroidUnwinder* guest_unwinder = nullptr) {
Thread thread;
thread.set_id(thread_info.tid);
@@ -509,6 +510,27 @@
auto& threads = *tombstone->mutable_threads();
threads[thread_info.tid] = thread;
+
+ if (guest_unwinder) {
+ if (!thread_info.guest_registers) {
+ async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+ "No guest state registers information for tid %d", thread_info.tid);
+ return;
+ }
+ Thread guest_thread;
+ unwindstack::AndroidUnwinderData guest_data;
+ guest_data.saved_initial_regs = std::make_optional<std::unique_ptr<unwindstack::Regs>>();
+ if (guest_unwinder->Unwind(thread_info.guest_registers.get(), guest_data)) {
+ dump_thread_backtrace(guest_data.frames, guest_thread);
+ } else {
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Unwind guest state registers failed for tid %d: Error %s",
+ thread_info.tid, guest_data.GetErrorString().c_str());
+ }
+ dump_registers(guest_unwinder, *guest_data.saved_initial_regs, guest_thread, memory_dump);
+ auto& guest_threads = *tombstone->mutable_guest_threads();
+ guest_threads[thread_info.tid] = guest_thread;
+ }
}
static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
@@ -686,10 +708,17 @@
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_tid,
- const ProcessInfo& process_info, const OpenFilesList* open_files) {
+ const ProcessInfo& process_info, const OpenFilesList* open_files,
+ const Architecture* guest_arch,
+ unwindstack::AndroidUnwinder* guest_unwinder) {
Tombstone result;
result.set_arch(get_arch());
+ if (guest_arch != nullptr) {
+ result.set_guest_arch(*guest_arch);
+ } else {
+ result.set_guest_arch(Architecture::NONE);
+ }
result.set_build_fingerprint(android::base::GetProperty("ro.build.fingerprint", "unknown"));
result.set_revision(android::base::GetProperty("ro.revision", "unknown"));
result.set_timestamp(get_timestamp());
@@ -750,11 +779,11 @@
dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
dump_crash_details(&result, unwinder->GetProcessMemory(), process_info);
// Dump the target thread, but save the memory around the registers.
- dump_thread(&result, unwinder, target_thread, /* memory_dump */ true);
+ dump_thread(&result, unwinder, target_thread, /* memory_dump */ true, guest_unwinder);
for (const auto& [tid, thread_info] : threads) {
if (tid != target_tid) {
- dump_thread(&result, unwinder, thread_info);
+ dump_thread(&result, unwinder, thread_info, /* memory_dump */ false, guest_unwinder);
}
}
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 08c1cc0..1900719 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -79,8 +79,8 @@
return describe_end(value, desc);
}
-static const char* abi_string(const Tombstone& tombstone) {
- switch (tombstone.arch()) {
+static const char* abi_string(const Architecture& arch) {
+ switch (arch) {
case Architecture::ARM32:
return "arm";
case Architecture::ARM64:
@@ -578,11 +578,28 @@
}
}
+static void print_guest_thread(CallbackType callback, const Tombstone& tombstone,
+ const Thread& guest_thread, pid_t tid, bool should_log) {
+ CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---");
+ CBS("Guest thread information for tid: %d", tid);
+ print_thread_registers(callback, tombstone, guest_thread, should_log);
+
+ CBS("");
+ CB(true, "%d total frames", guest_thread.current_backtrace().size());
+ CB(true, "backtrace:");
+ print_backtrace(callback, tombstone, guest_thread.current_backtrace(), should_log);
+
+ print_thread_memory_dump(callback, tombstone, guest_thread);
+}
+
bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) {
CBL("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***");
CBL("Build fingerprint: '%s'", tombstone.build_fingerprint().c_str());
CBL("Revision: '%s'", tombstone.revision().c_str());
- CBL("ABI: '%s'", abi_string(tombstone));
+ CBL("ABI: '%s'", abi_string(tombstone.arch()));
+ if (tombstone.guest_arch() != Architecture::NONE) {
+ CBL("Guest architecture: '%s'", abi_string(tombstone.guest_arch()));
+ }
CBL("Timestamp: %s", tombstone.timestamp().c_str());
CBL("Process uptime: %ds", tombstone.process_uptime());
@@ -607,6 +624,12 @@
print_logs(callback, tombstone, 50);
+ const auto& guest_threads = tombstone.guest_threads();
+ auto main_guest_thread_it = guest_threads.find(tombstone.tid());
+ if (main_guest_thread_it != threads.end()) {
+ print_guest_thread(callback, tombstone, main_guest_thread_it->second, tombstone.tid(), true);
+ }
+
// protobuf's map is unordered, so sort the keys first.
std::set<int> thread_ids;
for (const auto& [tid, _] : threads) {
@@ -618,6 +641,10 @@
for (const auto& tid : thread_ids) {
CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---");
print_thread(callback, tombstone, threads.find(tid)->second);
+ auto guest_thread_it = guest_threads.find(tid);
+ if (guest_thread_it != guest_threads.end()) {
+ print_guest_thread(callback, tombstone, guest_thread_it->second, tid, false);
+ }
}
if (tombstone.open_fds().size() > 0) {
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index e70d525..6f9cd96 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -22,6 +22,7 @@
message Tombstone {
Architecture arch = 1;
+ Architecture guest_arch = 24;
string build_fingerprint = 2;
string revision = 3;
string timestamp = 4;
@@ -42,6 +43,7 @@
repeated Cause causes = 15;
map<uint32, Thread> threads = 16;
+ map<uint32, Thread> guest_threads = 25;
repeated MemoryMapping memory_mappings = 17;
repeated LogBuffer log_buffers = 18;
repeated FD open_fds = 19;
@@ -49,7 +51,7 @@
uint32 page_size = 22;
bool has_been_16kb_mode = 23;
- reserved 24 to 999;
+ reserved 26 to 999;
}
enum Architecture {
@@ -58,8 +60,9 @@
X86 = 2;
X86_64 = 3;
RISCV64 = 4;
+ NONE = 5;
- reserved 5 to 999;
+ reserved 6 to 999;
}
message Signal {
diff --git a/debuggerd/test_permissive_mte/AndroidTest.xml b/debuggerd/test_permissive_mte/AndroidTest.xml
index bd3d018..db5f5b8 100644
--- a/debuggerd/test_permissive_mte/AndroidTest.xml
+++ b/debuggerd/test_permissive_mte/AndroidTest.xml
@@ -17,8 +17,6 @@
<option name="test-suite-tag" value="init_test_upgrade_mte" />
<option name="test-suite-tag" value="apct" />
- <!-- For tombstone inspection. -->
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="mte_crash->/data/local/tmp/mte_crash" />
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 914b4a6..402eb82 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -503,6 +503,8 @@
enabled: false,
},
},
+ stl: "libc++_static",
+ static_executable: true,
}
python_library_host {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
index 21dc666..635a38c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
@@ -17,6 +17,8 @@
#pragma once
#include <memory>
+#include <vector>
+
#include "libsnapshot/cow_format.h"
namespace android {
@@ -50,4 +52,4 @@
const uint32_t block_size_;
};
} // namespace snapshot
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 3f49c69..3389f58 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -19,6 +19,7 @@
#include <memory>
#include <optional>
#include <unordered_map>
+#include <vector>
#include <android-base/unique_fd.h>
#include <libsnapshot/cow_format.h>
diff --git a/init/devices.cpp b/init/devices.cpp
index e76786a..5560c20 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -25,6 +25,7 @@
#include <filesystem>
#include <memory>
#include <string>
+#include <string_view>
#include <thread>
#include <android-base/chrono_utils.h>
@@ -377,8 +378,8 @@
if (FindPlatformDevice(uevent.path, &device)) {
// Skip /devices/platform or /devices/ if present
- static const std::string devices_platform_prefix = "/devices/platform/";
- static const std::string devices_prefix = "/devices/";
+ static constexpr std::string_view devices_platform_prefix = "/devices/platform/";
+ static constexpr std::string_view devices_prefix = "/devices/";
if (StartsWith(device, devices_platform_prefix)) {
device = device.substr(devices_platform_prefix.length());
@@ -434,6 +435,7 @@
if (ReadFileToString("/sys/class/block/" + uevent.device_name + "/queue/zoned", &model) &&
!StartsWith(model, "none")) {
links.emplace_back("/dev/block/by-name/zoned_device");
+ links.emplace_back("/dev/sys/block/by-name/zoned_device");
}
auto last_slash = uevent.path.rfind('/');
@@ -482,11 +484,21 @@
// event.
if (action == "add" || (action == "change" && StartsWith(devpath, "/dev/block/dm-"))) {
for (const auto& link : links) {
+ std::string target;
+ if (StartsWith(link, "/dev/block/")) {
+ target = devpath;
+ } else if (StartsWith(link, "/dev/sys/block/")) {
+ target = "/sys/class/block/" + Basename(devpath);
+ } else {
+ LOG(ERROR) << "Unrecognized link type: " << link;
+ continue;
+ }
+
if (!mkdir_recursive(Dirname(link), 0755)) {
PLOG(ERROR) << "Failed to create directory " << Dirname(link);
}
- if (symlink(devpath.c_str(), link.c_str())) {
+ if (symlink(target.c_str(), link.c_str())) {
if (errno != EEXIST) {
PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link;
} else if (std::string link_path;
diff --git a/init/devices.h b/init/devices.h
index 44ce2a9..6da1232 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -127,9 +127,6 @@
virtual ~DeviceHandler() = default;
void HandleUevent(const Uevent& uevent) override;
- void ColdbootDone() override;
-
- std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
// `androidboot.partition_map` allows associating a partition name for a raw block device
// through a comma separated and semicolon deliminated list. For example,
@@ -138,11 +135,13 @@
static std::string GetPartitionNameForDevice(const std::string& device);
private:
+ void ColdbootDone() override;
bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
const std::string& path, const std::vector<std::string>& links) const;
void MakeDevice(const std::string& path, bool block, int major, int minor,
const std::vector<std::string>& links) const;
+ std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
void HandleDevice(const std::string& action, const std::string& devpath, bool block, int major,
int minor, const std::vector<std::string>& links) const;
void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 3c012fe..01957ef 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -264,8 +264,9 @@
return uevent.firmware;
}
-void FirmwareHandler::ProcessFirmwareEvent(const std::string& root,
+void FirmwareHandler::ProcessFirmwareEvent(const std::string& path,
const std::string& firmware) const {
+ std::string root = "/sys" + path;
std::string loading = root + "/loading";
std::string data = root + "/data";
@@ -296,6 +297,7 @@
", fstat failed: " + strerror(errno));
return false;
}
+ LOG(INFO) << "found " << file << " for " << path;
LoadFirmware(firmware, root, fw_fd.get(), sb.st_size, loading_fd.get(), data_fd.get());
return true;
};
@@ -362,7 +364,7 @@
if (pid == 0) {
Timer t;
auto firmware = GetFirmwarePath(uevent);
- ProcessFirmwareEvent("/sys" + uevent.path, firmware);
+ ProcessFirmwareEvent(uevent.path, firmware);
LOG(INFO) << "loading " << uevent.path << " took " << t;
_exit(EXIT_SUCCESS);
}
diff --git a/init/firmware_handler.h b/init/firmware_handler.h
index d2f7347..fceb392 100644
--- a/init/firmware_handler.h
+++ b/init/firmware_handler.h
@@ -57,7 +57,7 @@
Result<std::string> RunExternalHandler(const std::string& handler, uid_t uid, gid_t gid,
const Uevent& uevent) const;
std::string GetFirmwarePath(const Uevent& uevent) const;
- void ProcessFirmwareEvent(const std::string& root, const std::string& firmware) const;
+ void ProcessFirmwareEvent(const std::string& path, const std::string& firmware) const;
bool ForEachFirmwareDirectory(std::function<bool(const std::string&)> handler) const;
std::vector<std::string> firmware_directories_;
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 753ed6b..2fef9d3 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -32,6 +32,7 @@
#define __ANDROID_API_S__ 31
#define __ANDROID_API_T__ 33
#define __ANDROID_API_U__ 34
+#define __ANDROID_API_V__ 35
// sys/system_properties.h
#define PROP_VALUE_MAX 92
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 7e8513b..b2f586b 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -630,7 +630,7 @@
ASSERT_TRUE(parser.ParseConfig(tf.path));
- if (GetIntProperty("ro.vendor.api_level", 0) > __ANDROID_API_U__) {
+ if (GetIntProperty("ro.vendor.api_level", 0) > __ANDROID_API_V__) {
ASSERT_EQ(1u, parser.parse_error_count());
} else {
ASSERT_EQ(0u, parser.parse_error_count());
diff --git a/init/property_service.cpp b/init/property_service.cpp
index d3cdd43..cd5933d 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -974,6 +974,17 @@
std::string build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
+
+ // should be set in /product/etc/build.prop
+ // when we have a dev option device, and we've switched the kernel to 16kb mode
+ // we use the same system image, but we've switched out the kernel, so make it
+ // visible at a high level
+ bool has16KbDevOption =
+ android::base::GetBoolProperty("ro.product.build.16k_page.enabled", false);
+ if (has16KbDevOption && getpagesize() == 16384) {
+ build_fingerprint += "_16kb";
+ }
+
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.product.device", UNKNOWN);
build_fingerprint += ':';
diff --git a/init/security.cpp b/init/security.cpp
index 3e15447..a0d63bc 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -114,10 +114,9 @@
return {};
}
#elif defined(__riscv)
- // TODO: sv48 and sv57 have both been added to the kernel, but the kernel
- // still doesn't support more than 24 bits.
- // https://github.com/google/android-riscv64/issues/1
- if (SetMmapRndBitsMin(24, 24, false)) {
+ // riscv64 supports 24 rnd bits with Sv39, and starting with the 6.9 kernel,
+ // 33 bits with Sv48 and Sv57.
+ if (SetMmapRndBitsMin(33, 24, false)) {
return {};
}
#elif defined(__x86_64__)
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 92e350b..6f3e368 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -680,12 +680,12 @@
}
if (service_->proc_attr_.parsed_uid == std::nullopt) {
- if (android::base::GetIntProperty("ro.vendor.api_level", 0) > __ANDROID_API_U__) {
+ if (android::base::GetIntProperty("ro.vendor.api_level", 0) > __ANDROID_API_V__) {
return Error() << "No user specified for service '" << service_->name()
- << "'. Defaults to root.";
+ << "', so it would have been root.";
} else {
LOG(WARNING) << "No user specified for service '" << service_->name()
- << "'. Defaults to root.";
+ << "', so it is root.";
}
}
diff --git a/init/test_upgrade_mte/AndroidTest.xml b/init/test_upgrade_mte/AndroidTest.xml
index b89cde8..e08afc0 100644
--- a/init/test_upgrade_mte/AndroidTest.xml
+++ b/init/test_upgrade_mte/AndroidTest.xml
@@ -20,11 +20,13 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="remount-system" value="true" />
- <option name="push" value="mte_upgrade_test.rc->/system/etc/init/mte_upgrade_test.rc" />
- <option name="push" value="mte_upgrade_test_helper->/system/bin/mte_upgrade_test_helper" />
- <option name="push" value="mte_upgrade_test_helper->/data/local/tmp/app_process64" />
+
+ <option name="push-file" key="mte_upgrade_test.rc" value="/system/etc/init/mte_upgrade_test.rc" />
+ <option name="push-file" key="mte_upgrade_test_helper" value="/system/bin/mte_upgrade_test_helper" />
+ <option name="push-file" key="mte_upgrade_test_helper" value="/data/local/tmp/app_process64" />
+ <option name="post-push" value="chmod 644 /system/etc/init/mte_upgrade_test.rc" />
</target_preparer>
<test class="com.android.tradefed.testtype.HostTest" >
<option name="jar" value="mte_upgrade_test.jar" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/init/test_upgrade_mte/OWNERS b/init/test_upgrade_mte/OWNERS
new file mode 100644
index 0000000..79625df
--- /dev/null
+++ b/init/test_upgrade_mte/OWNERS
@@ -0,0 +1,5 @@
+fmayer@google.com
+
+eugenis@google.com
+mitchp@google.com
+pcc@google.com
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 6728cc6..c4b175a 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -22,6 +22,7 @@
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
+
#include <memory>
int MaybeDowngrade() {
@@ -65,7 +66,5 @@
// This binary gets run by src/com/android/tests/init/MteUpgradeTest.java, which
// asserts that it crashes as expected.
f[17] = 'x';
- char buf[1];
- read(1, buf, 1);
return 0;
}
diff --git a/init/util.cpp b/init/util.cpp
index e5efc7d..375e905 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -570,6 +570,8 @@
{"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE},
{"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE},
{"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS},
+ {"--force", SELINUX_ANDROID_RESTORECON_FORCE},
+ {"--data-data", SELINUX_ANDROID_RESTORECON_DATADATA},
{0, 0}};
int flag = 0;
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index 2559137..b2af06c 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -24,9 +24,6 @@
ramdisk_available: true,
vendor_ramdisk_available: true,
recovery_available: true,
- vndk: {
- enabled: true,
- },
host_supported: true,
srcs: [
"android_pubkey.cpp",
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index b7752d9..e297581 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -129,10 +129,7 @@
cc_library {
name: "libcutils",
defaults: ["libcutils_defaults"],
- vndk: {
- enabled: true,
- support_system_process: true,
- },
+ double_loadable: true,
srcs: [
"config_utils.cpp",
"iosched_policy.cpp",
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 5efe209..c34cd71 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -68,10 +68,6 @@
{ 01771, AID_SYSTEM, AID_MISC, 0, "data/misc" },
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest64" },
{ 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
@@ -143,12 +139,6 @@
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" },
{ 00644, AID_APP, AID_APP, 0, "data/data/*" },
{ 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" },
- { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest/tests.txt" },
- { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest64/tests.txt" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest/*" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64/*" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest/*" },
- { 00750, AID_ROOT, AID_SHELL, 0, "data/benchmarktest64/*" },
{ 00600, AID_ROOT, AID_ROOT, 0, "default.prop" }, // legacy
{ 00600, AID_ROOT, AID_ROOT, 0, "system/etc/prop.default" },
{ 00600, AID_ROOT, AID_ROOT, 0, "odm/build.prop" }, // legacy; only for P release
diff --git a/libnetutils/Android.bp b/libnetutils/Android.bp
index 02bd2e3..0bca662 100644
--- a/libnetutils/Android.bp
+++ b/libnetutils/Android.bp
@@ -18,9 +18,6 @@
cc_library_shared {
name: "libnetutils",
vendor_available: true,
- vndk: {
- enabled: true,
- },
srcs: [
"dhcpclient.c",
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index bb855d5..d40be9f 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -72,10 +72,7 @@
recovery_available: true,
vendor_available: true,
product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
+ double_loadable: true,
shared_libs: [
"libbase",
"libcgrouprc",
diff --git a/libstats/socket_lazy/Android.bp b/libstats/socket_lazy/Android.bp
index b2cd7b2..241e87a 100644
--- a/libstats/socket_lazy/Android.bp
+++ b/libstats/socket_lazy/Android.bp
@@ -7,6 +7,12 @@
cc_library_static {
name: "libstatssocket_lazy",
+ local_include_dirs: [
+ "include",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
header_libs: [
"libstatssocket_headers",
],
@@ -28,7 +34,10 @@
"-Wall",
"-Werror",
],
- test_suites: ["device-tests", "mts-statsd"],
+ test_suites: [
+ "device-tests",
+ "mts-statsd",
+ ],
test_config: "libstatssocket_lazy_test.xml",
// TODO(b/153588990): Remove when the build system properly separates.
// 32bit and 64bit architectures.
diff --git a/libstats/socket_lazy/include/statssocket_lazy.h b/libstats/socket_lazy/include/statssocket_lazy.h
new file mode 100644
index 0000000..7dda0ba
--- /dev/null
+++ b/libstats/socket_lazy/include/statssocket_lazy.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 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
+
+namespace android::statssocket::lazy {
+
+// See if libstatssocket.so is available. Early processes relying on _lazy might not have access
+// to libstatssocket.so when they start before the StatsD APEX is available.
+bool IsAvailable();
+
+} // namespace android::statssocket::lazy
diff --git a/libstats/socket_lazy/libstatssocket_lazy.cpp b/libstats/socket_lazy/libstatssocket_lazy.cpp
index fe94ef2..d907c7e 100644
--- a/libstats/socket_lazy/libstatssocket_lazy.cpp
+++ b/libstats/socket_lazy/libstatssocket_lazy.cpp
@@ -23,8 +23,10 @@
#include "log/log.h"
-#include "stats_event.h"
-#include "stats_socket.h"
+#include <stats_event.h>
+#include <stats_socket.h>
+
+#include "statssocket_lazy.h"
// This file provides a lazy interface to libstatssocket.so to address early boot dependencies.
// Specifically bootanimation, surfaceflinger, and lmkd run before the statsd APEX is loaded and
@@ -77,6 +79,13 @@
return dlopen("libstatssocket.so", dlopen_flags);
}
+namespace android::statssocket::lazy {
+bool IsAvailable() {
+ static const void* handle = LoadLibstatssocket(RTLD_NOW);
+ return handle != nullptr;
+}
+} // namespace android::statssocket::lazy
+
//
// Initialization and symbol binding.
diff --git a/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp b/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
index 3de6cd7..733f1e4 100644
--- a/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
+++ b/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
@@ -21,6 +21,8 @@
#include "stats_event.h"
#include "stats_socket.h"
+#include "statssocket_lazy.h"
+
// The tests here are just for the case when libstatssocket.so cannot be loaded by
// libstatssocket_lazy.
class LibstatssocketLazyTest : public ::testing::Test {
@@ -57,3 +59,7 @@
TEST_F(LibstatssocketLazyTest, NoLibstatssocketForStatsSocket) {
EXPECT_DEATH(AStatsSocket_close(), kLoadFailed);
}
+
+TEST_F(LibstatssocketLazyTest, IsAvailableFalse) {
+ EXPECT_FALSE(android::statssocket::lazy::IsAvailable());
+}
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
index 1b41a6b..842db40 100644
--- a/libsysutils/Android.bp
+++ b/libsysutils/Android.bp
@@ -5,9 +5,6 @@
cc_library {
name: "libsysutils",
vendor_available: true,
- vndk: {
- enabled: true,
- },
srcs: [
"src/SocketListener.cpp",
diff --git a/libusbhost/Android.bp b/libusbhost/Android.bp
index 9ae73d0..f8a73ad 100644
--- a/libusbhost/Android.bp
+++ b/libusbhost/Android.bp
@@ -21,9 +21,6 @@
cc_library {
name: "libusbhost",
vendor_available: true,
- vndk: {
- enabled: true,
- },
host_supported: true,
srcs: ["usbhost.c"],
cflags: ["-Werror"],
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 1741187..ba19ace 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -183,10 +183,7 @@
name: "libutils",
defaults: ["libutils_impl_defaults"],
- vndk: {
- enabled: true,
- support_system_process: true,
- },
+ double_loadable: true,
target: {
product: {
@@ -228,10 +225,7 @@
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
min_sdk_version: "29",
- vndk: {
- enabled: true,
- support_system_process: true,
- },
+ double_loadable: true,
header_libs: [
"libbase_headers",
diff --git a/libutils/binder/String16_test.cpp b/libutils/binder/String16_test.cpp
index 6f4642e..83cc599 100644
--- a/libutils/binder/String16_test.cpp
+++ b/libutils/binder/String16_test.cpp
@@ -16,6 +16,8 @@
#include <utils/String16.h>
#include <utils/String8.h>
+#include <compare>
+#include <utility>
#include <gtest/gtest.h>
@@ -257,3 +259,45 @@
EXPECT_EQ(NO_MEMORY, s.insert(3, u"", SIZE_MAX));
EXPECT_STR16EQ(u"foo!bar", s.c_str());
}
+
+TEST(String16Test, comparisons) {
+ const char16_t* cstr1 = u"abc";
+ const char16_t* cstr2 = u"def";
+
+ // str1 and str1b will point to different blocks of memory but with equal contents.
+ String16 str1(cstr1);
+ String16 str1b(cstr1);
+ String16 str2(cstr2);
+
+ EXPECT_TRUE((str1 <=> str1b) == 0);
+ EXPECT_FALSE(str1 != str1b);
+ EXPECT_FALSE(str1 < str1b);
+ EXPECT_TRUE(str1 <= str1b);
+ EXPECT_TRUE(str1 == str1b);
+ EXPECT_TRUE(str1 >= str1b);
+ EXPECT_FALSE(str1 > str1b);
+
+ EXPECT_TRUE((str1 <=> str2) < 0);
+ EXPECT_TRUE((str2 <=> str1) > 0);
+ EXPECT_TRUE(str1 != str2);
+ EXPECT_TRUE(str1 < str2);
+ EXPECT_TRUE(str1 <= str2);
+ EXPECT_FALSE(str1 == str2);
+ EXPECT_FALSE(str1 >= str2);
+ EXPECT_FALSE(str1 > str2);
+
+ // Verify that pre-C++20 comparison operators work with a std::pair of a String8, which only
+ // provides <=> in C++20 and up. See b/339775405.
+
+ std::pair<String16, int> pair1(str1, 13);
+ std::pair<String16, int> pair1b(str1b, 13);
+ std::pair<String16, int> pair2(str2, 13);
+
+ EXPECT_TRUE(pair1 == pair1b);
+ EXPECT_FALSE(pair1 < pair1b);
+ EXPECT_FALSE(pair1 > pair1b);
+
+ EXPECT_TRUE(pair1 != pair2);
+ EXPECT_TRUE(pair1 < pair2);
+ EXPECT_FALSE(pair1 > pair2);
+}
diff --git a/libutils/binder/String8_test.cpp b/libutils/binder/String8_test.cpp
index 6f7882a..fc3c329 100644
--- a/libutils/binder/String8_test.cpp
+++ b/libutils/binder/String8_test.cpp
@@ -17,8 +17,10 @@
#define LOG_TAG "String8_test"
#include <log/log.h>
-#include <utils/String8.h>
#include <utils/String16.h>
+#include <utils/String8.h>
+#include <compare>
+#include <utility>
#include <gtest/gtest.h>
@@ -132,3 +134,45 @@
EXPECT_TRUE(s.removeAll("o"));
EXPECT_STREQ("Hell, wrld!", s.c_str());
}
+
+TEST_F(String8Test, comparisons) {
+ const char* cstr1 = "abc";
+ const char* cstr2 = "def";
+
+ // str1 and str1b will point to different blocks of memory but with equal contents.
+ String8 str1(cstr1);
+ String8 str1b(cstr1);
+ String8 str2(cstr2);
+
+ EXPECT_TRUE((str1 <=> str1b) == 0);
+ EXPECT_FALSE(str1 != str1b);
+ EXPECT_FALSE(str1 < str1b);
+ EXPECT_TRUE(str1 <= str1b);
+ EXPECT_TRUE(str1 == str1b);
+ EXPECT_TRUE(str1 >= str1b);
+ EXPECT_FALSE(str1 > str1b);
+
+ EXPECT_TRUE((str1 <=> str2) < 0);
+ EXPECT_TRUE((str2 <=> str1) > 0);
+ EXPECT_TRUE(str1 != str2);
+ EXPECT_TRUE(str1 < str2);
+ EXPECT_TRUE(str1 <= str2);
+ EXPECT_FALSE(str1 == str2);
+ EXPECT_FALSE(str1 >= str2);
+ EXPECT_FALSE(str1 > str2);
+
+ // Verify that pre-C++20 comparison operators work with a std::pair of a String8, which only
+ // provides <=> in C++20 and up. See b/339775405.
+
+ std::pair<String8, int> pair1(str1, 13);
+ std::pair<String8, int> pair1b(str1b, 13);
+ std::pair<String8, int> pair2(str2, 13);
+
+ EXPECT_TRUE(pair1 == pair1b);
+ EXPECT_FALSE(pair1 < pair1b);
+ EXPECT_FALSE(pair1 > pair1b);
+
+ EXPECT_TRUE(pair1 != pair2);
+ EXPECT_TRUE(pair1 < pair2);
+ EXPECT_FALSE(pair1 > pair2);
+}
diff --git a/libutils/binder/include/utils/String16.h b/libutils/binder/include/utils/String16.h
index c713576..867dbac 100644
--- a/libutils/binder/include/utils/String16.h
+++ b/libutils/binder/include/utils/String16.h
@@ -29,6 +29,10 @@
#define HAS_STRING_VIEW
#endif
+#if __cplusplus >= 202002L
+#include <compare>
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
@@ -105,6 +109,9 @@
inline bool operator!=(const String16& other) const;
inline bool operator>=(const String16& other) const;
inline bool operator>(const String16& other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const String16& other) const;
+#endif
inline bool operator<(const char16_t* other) const;
inline bool operator<=(const char16_t* other) const;
@@ -112,6 +119,9 @@
inline bool operator!=(const char16_t* other) const;
inline bool operator>=(const char16_t* other) const;
inline bool operator>(const char16_t* other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const char16_t* other) const;
+#endif
inline operator const char16_t*() const;
@@ -334,6 +344,19 @@
return strzcmp16(mString, size(), other.mString, other.size()) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String16::operator<=>(const String16& other) const {
+ int result = strzcmp16(mString, size(), other.mString, other.size());
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline bool String16::operator<(const char16_t* other) const
{
return strcmp16(mString, other) < 0;
@@ -364,6 +387,19 @@
return strcmp16(mString, other) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String16::operator<=>(const char16_t* other) const {
+ int result = strcmp16(mString, other);
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline String16::operator const char16_t*() const
{
return mString;
diff --git a/libutils/binder/include/utils/String8.h b/libutils/binder/include/utils/String8.h
index 6d25072..e0d7588 100644
--- a/libutils/binder/include/utils/String8.h
+++ b/libutils/binder/include/utils/String8.h
@@ -36,6 +36,10 @@
#define HAS_STRING_VIEW
#endif
+#if __cplusplus >= 202002L
+#include <compare>
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
@@ -106,6 +110,9 @@
inline bool operator!=(const String8& other) const;
inline bool operator>=(const String8& other) const;
inline bool operator>(const String8& other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const String8& other) const;
+#endif
inline bool operator<(const char* other) const;
inline bool operator<=(const char* other) const;
@@ -113,6 +120,9 @@
inline bool operator!=(const char* other) const;
inline bool operator>=(const char* other) const;
inline bool operator>(const char* other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const char* other) const;
+#endif
inline operator const char*() const;
@@ -302,6 +312,19 @@
return strcmp(mString, other.mString) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String8::operator<=>(const String8& other) const {
+ int result = strcmp(mString, other.mString);
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline bool String8::operator<(const char* other) const
{
return strcmp(mString, other) < 0;
@@ -332,6 +355,19 @@
return strcmp(mString, other) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String8::operator<=>(const char* other) const {
+ int result = strcmp(mString, other);
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline String8::operator const char*() const
{
return mString;
diff --git a/mkbootfs/mkbootfs.c b/mkbootfs/mkbootfs.c
index d3922bf..84a0a4e 100644
--- a/mkbootfs/mkbootfs.c
+++ b/mkbootfs/mkbootfs.c
@@ -402,7 +402,7 @@
static void usage(void)
{
fprintf(stderr,
- "Usage: mkbootfs [-n FILE] [-d DIR|-F FILE] DIR...\n"
+ "Usage: mkbootfs [-n FILE] [-d DIR|-f FILE] DIR...\n"
"\n"
"\t-d, --dirname=DIR: fs-config directory\n"
"\t-f, --file=FILE: Canned configuration file\n"
@@ -410,11 +410,11 @@
"\t-n, --nodes=FILE: Dev nodes description file\n"
"\n"
"Dev nodes description:\n"
- "\t[dir|nod] [perms] [uid] [gid] [c|b] [minor] [major]\n"
+ "\t[dir|nod] [perms] [uid] [gid] [c|b] [major] [minor]\n"
"\tExample:\n"
"\t\t# My device nodes\n"
"\t\tdir dev 0755 0 0\n"
- "\t\tnod dev/null 0600 0 0 c 1 5\n"
+ "\t\tnod dev/null 0600 0 0 c 1 3\n"
);
}
@@ -445,11 +445,6 @@
int num_dirs = argc - optind;
argv += optind;
- if (num_dirs <= 0) {
- usage();
- errx(1, "no directories to process?!");
- }
-
while(num_dirs-- > 0){
char *x = strchr(*argv, '=');
if(x != 0) {
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index 108c7c2..bd24f22 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -117,3 +117,7 @@
llndk_libraries_txt {
name: "llndk.libraries.txt",
}
+
+sanitizer_libraries_txt {
+ name: "sanitizer.libraries.txt",
+}
\ No newline at end of file
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 2394b14..06e8730 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -211,26 +211,6 @@
$(hide) sed -i -e 's?%EXPORT_GLOBAL_SCUDO_ALLOCATION_RING_BUFFER_SIZE%?$(EXPORT_GLOBAL_SCUDO_ALLOCATION_RING_BUFFER_SIZE)?g' $@
#######################################
-# sanitizer.libraries.txt
-include $(CLEAR_VARS)
-LOCAL_MODULE := sanitizer.libraries.txt
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-LOCAL_MODULE_STEM := $(LOCAL_MODULE)
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_SANITIZER_RUNTIME_LIBRARIES := \
- $(SANITIZER_STEMS) \
- $(2ND_SANITIZER_STEMS)
-$(LOCAL_BUILT_MODULE):
- @echo "Generate: $@"
- @mkdir -p $(dir $@)
- $(hide) echo -n > $@
- $(hide) $(foreach lib,$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES), \
- echo $(lib) >> $@;)
-
-#######################################
# ramdisk_node_list
include $(CLEAR_VARS)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f7f0cc3..5953769 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -637,11 +637,11 @@
mkdir /metadata/aconfig 0775 root system
mkdir /metadata/aconfig/flags 0770 root system
+ mkdir /metadata/aconfig/maps 0775 root system
mkdir /metadata/aconfig/boot 0775 root system
mkdir /metadata/aconfig_test_missions 0775 root system
- exec_start aconfigd-init
- start aconfigd
+ exec_start aconfigd-platform-init
on late-fs
# Ensure that tracefs has the correct permissions.
@@ -1031,6 +1031,8 @@
# Wait for apexd to finish activating APEXes before starting more processes.
wait_for_prop apexd.status activated
perform_apex_config
+ exec_start aconfigd-mainline-init
+ start aconfigd
# Create directories for boot animation.
mkdir /data/misc/bootanim 0755 system system