Merge "libmodprobe: LPM: Cleanup of redundant check"
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 844357c..3b8866e 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -459,6 +459,8 @@
{"reboot,sys_ldo_ok,pmic,main", 227},
{"reboot,sys_ldo_ok,pmic,sub", 228},
{"reboot,smpl_timeout,pmic,main", 229},
+ {"reboot,ota,.*", 230},
+ {"reboot,periodic,.*", 231},
};
// Converts a string value representing the reason the system booted to an
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index 23f01d1..22bd0e7 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -40,15 +40,6 @@
chown system log /data/misc/bootstat/time_since_last_boot
# end ota transitional support
-# Record the time at which the user has successfully entered the pin to decrypt
-# the device, /data is decrypted, and the system is entering the main boot phase.
-#
-# post-fs-data: /data is writable
-# property:init.svc.bootanim=running: The boot animation is running
-# property:ro.crypto.type=block: FDE device
-on post-fs-data && property:init.svc.bootanim=running && property:ro.crypto.type=block
- exec_background - system log -- /system/bin/bootstat -r post_decrypt_time_elapsed
-
# Initialize bootstat state machine.
#
# sys.bootstat.first_boot_completed: responsible for making sure that record_boot_complete happens
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 15b5813..d20de6b 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -98,6 +98,7 @@
"libbase_headers",
"libdebuggerd_common_headers",
"bionic_libc_platform_headers",
+ "gwp_asan_headers",
],
whole_static_libs: [
@@ -367,6 +368,7 @@
name: "crash_dump",
srcs: [
"crash_dump.cpp",
+ "tombstone_handler.cpp",
"util.cpp",
],
defaults: ["debuggerd_defaults"],
@@ -508,6 +510,9 @@
arm64: {
src: "seccomp_policy/crash_dump.arm.policy",
},
+ riscv64: {
+ enabled: false,
+ },
x86: {
src: "seccomp_policy/crash_dump.x86_64.policy",
},
diff --git a/debuggerd/TEST_MAPPING b/debuggerd/TEST_MAPPING
index 394447b..8633cb8 100644
--- a/debuggerd/TEST_MAPPING
+++ b/debuggerd/TEST_MAPPING
@@ -5,6 +5,9 @@
},
{
"name": "libtombstoned_client_rust_test"
+ },
+ {
+ "name": "MicrodroidHostTestCases"
}
],
"hwasan-presubmit": [
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index b302918..bd1e91d 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -216,7 +216,7 @@
log_error(output_fd, 0,
"received packet of unexpected length from tombstoned while reading %s response: "
"expected %zd, received %zd",
- kind, sizeof(response), rc);
+ kind, sizeof(*response), rc);
return false;
}
return true;
@@ -276,6 +276,13 @@
return false;
}
+ // WARNING: It's not possible to replace the below with a splice call.
+ // Due to the way debuggerd does many small writes across the pipe,
+ // this would cause splice to copy a page for each write. The second
+ // pipe fills up based on the number of pages being copied, even
+ // though there is not much data being transferred per page. When
+ // the second pipe is full, everything stops since there is nothing
+ // reading the second pipe to clear it.
char buf[1024];
rc = TEMP_FAILURE_RETRY(read(pipe_read.get(), buf, sizeof(buf)));
if (rc == 0) {
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index ebb8d86..33ff05f 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <stdio.h>
+#include <sys/eventfd.h>
#include <unistd.h>
#include <chrono>
@@ -51,23 +52,35 @@
TEST(debuggerd_client, race) {
static int THREAD_COUNT = getThreadCount();
+
+ // Semaphore incremented once per thread started.
+ unique_fd barrier(eventfd(0, EFD_SEMAPHORE));
+ ASSERT_NE(-1, barrier.get());
+
pid_t forkpid = fork();
-
ASSERT_NE(-1, forkpid);
-
if (forkpid == 0) {
// Spawn a bunch of threads, to make crash_dump take longer.
std::vector<std::thread> threads;
+ threads.reserve(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; ++i) {
- threads.emplace_back([]() {
- while (true) {
- std::this_thread::sleep_for(60s);
+ threads.emplace_back([&barrier]() {
+ uint64_t count = 1;
+ ASSERT_NE(-1, write(barrier.get(), &count, sizeof(count)));
+ for (;;) {
+ pause();
}
});
}
+ for (;;) {
+ pause();
+ }
+ }
- std::this_thread::sleep_for(60s);
- exit(0);
+ // Wait for the child to spawn all of its threads.
+ for (int i = 0; i < THREAD_COUNT; ++i) {
+ uint64_t count;
+ ASSERT_NE(-1, read(barrier.get(), &count, sizeof(count)));
}
unique_fd pipe_read, pipe_write;
@@ -77,9 +90,6 @@
constexpr int PIPE_SIZE = 16 * 1024 * 1024;
ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE));
- // Wait for a bit to let the child spawn all of its threads.
- std::this_thread::sleep_for(1s);
-
ASSERT_TRUE(
debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 60000, std::move(pipe_write)));
// Immediately kill the forked child, to make sure that the dump didn't return early.
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index e3ea455..3563436 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -23,7 +23,6 @@
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
-#include <syscall.h>
#include <unistd.h>
#include <limits>
@@ -60,7 +59,7 @@
#include "libdebuggerd/utility.h"
#include "debuggerd/handler.h"
-#include "tombstoned/tombstoned.h"
+#include "tombstone_handler.h"
#include "protocol.h"
#include "util.h"
@@ -143,7 +142,8 @@
return false;
}
-static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data) {
+static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data,
+ bool recoverable_gwp_asan_crash) {
ATRACE_CALL();
android::base::unique_fd amfd(socket_local_client(
"/data/system/ndebugsocket", ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM));
@@ -166,19 +166,32 @@
return false;
}
- // Activity Manager protocol: binary 32-bit network-byte-order ints for the
- // pid and signal number, followed by the raw text of the dump, culminating
- // in a zero byte that marks end-of-data.
+ // Activity Manager protocol:
+ // - 32-bit network-byte-order: pid
+ // - 32-bit network-byte-order: signal number
+ // - byte: recoverable_gwp_asan_crash
+ // - bytes: raw text of the dump
+ // - null terminator
+
uint32_t datum = htonl(pid);
- if (!android::base::WriteFully(amfd, &datum, 4)) {
+ if (!android::base::WriteFully(amfd, &datum, sizeof(datum))) {
PLOG(ERROR) << "AM pid write failed";
return false;
}
+
datum = htonl(signal);
- if (!android::base::WriteFully(amfd, &datum, 4)) {
- PLOG(ERROR) << "AM signal write failed";
+ if (!android::base::WriteFully(amfd, &datum, sizeof(datum))) {
+ PLOG(ERROR) << "AM signo write failed";
return false;
}
+
+ uint8_t recoverable_gwp_asan_crash_byte = recoverable_gwp_asan_crash ? 1 : 0;
+ if (!android::base::WriteFully(amfd, &recoverable_gwp_asan_crash_byte,
+ sizeof(recoverable_gwp_asan_crash_byte))) {
+ PLOG(ERROR) << "AM recoverable_gwp_asan_crash_byte write failed";
+ return false;
+ }
+
if (!android::base::WriteFully(amfd, amfd_data.c_str(), amfd_data.size() + 1)) {
PLOG(ERROR) << "AM data write failed";
return false;
@@ -216,8 +229,8 @@
// If we abort before we get an output fd, contact tombstoned to let any
// potential listeners know that we failed.
if (!g_tombstoned_connected) {
- if (!tombstoned_connect(g_target_thread, &g_tombstoned_socket, &g_output_fd, &g_proto_fd,
- kDebuggerdAnyIntercept)) {
+ if (!connect_tombstone_server(g_target_thread, &g_tombstoned_socket, &g_output_fd,
+ &g_proto_fd, kDebuggerdAnyIntercept)) {
// We failed to connect, not much we can do.
LOG(ERROR) << "failed to connected to tombstoned to report failure";
_exit(1);
@@ -266,10 +279,12 @@
}
static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
- std::unique_ptr<unwindstack::Regs>* regs, ProcessInfo* process_info) {
+ std::unique_ptr<unwindstack::Regs>* regs, ProcessInfo* process_info,
+ bool* recoverable_gwp_asan_crash) {
std::aligned_storage<sizeof(CrashInfo) + 1, alignof(CrashInfo)>::type buf;
CrashInfo* crash_info = reinterpret_cast<CrashInfo*>(&buf);
ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &buf, sizeof(buf)));
+ *recoverable_gwp_asan_crash = false;
if (rc == -1) {
PLOG(FATAL) << "failed to read target ucontext";
} else {
@@ -304,6 +319,8 @@
process_info->scudo_stack_depot = crash_info->data.d.scudo_stack_depot;
process_info->scudo_region_info = crash_info->data.d.scudo_region_info;
process_info->scudo_ring_buffer = crash_info->data.d.scudo_ring_buffer;
+ process_info->scudo_ring_buffer_size = crash_info->data.d.scudo_ring_buffer_size;
+ *recoverable_gwp_asan_crash = crash_info->data.d.recoverable_gwp_asan_crash;
FALLTHROUGH_INTENDED;
case 1:
case 2:
@@ -468,6 +485,7 @@
std::map<pid_t, ThreadInfo> thread_info;
siginfo_t siginfo;
std::string error;
+ bool recoverable_gwp_asan_crash = false;
{
ATRACE_NAME("ptrace");
@@ -519,7 +537,8 @@
if (thread == g_target_thread) {
// Read the thread's registers along with the rest of the crash info out of the pipe.
- ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info);
+ ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info,
+ &recoverable_gwp_asan_crash);
info.siginfo = &siginfo;
info.signo = info.siginfo->si_signo;
@@ -584,8 +603,8 @@
{
ATRACE_NAME("tombstoned_connect");
LOG(INFO) << "obtaining output fd from tombstoned, type: " << dump_type;
- g_tombstoned_connected = tombstoned_connect(g_target_thread, &g_tombstoned_socket, &g_output_fd,
- &g_proto_fd, dump_type);
+ g_tombstoned_connected = connect_tombstone_server(g_target_thread, &g_tombstoned_socket,
+ &g_output_fd, &g_proto_fd, dump_type);
}
if (g_tombstoned_connected) {
@@ -649,7 +668,7 @@
if (fatal_signal) {
// Don't try to notify ActivityManager if it just crashed, or we might hang until timeout.
if (thread_info[target_process].thread_name != "system_server") {
- activity_manager_notify(target_process, signo, amfd_data);
+ activity_manager_notify(target_process, signo, amfd_data, recoverable_gwp_asan_crash);
}
}
@@ -660,7 +679,7 @@
"* Process %d has been suspended while crashing.\n"
"* To attach the debugger, run this on the host:\n"
"*\n"
- "* gdbclient.py -p %d\n"
+ "* lldbclient.py -p %d\n"
"*\n"
"***********************************************************",
target_process, target_process);
@@ -668,7 +687,8 @@
// Close stdout before we notify tombstoned of completion.
close(STDOUT_FILENO);
- if (g_tombstoned_connected && !tombstoned_notify_completion(g_tombstoned_socket.get())) {
+ if (g_tombstoned_connected &&
+ !notify_completion(g_tombstoned_socket.get(), g_output_fd.get(), g_proto_fd.get())) {
LOG(ERROR) << "failed to notify tombstoned of completion";
}
diff --git a/debuggerd/crasher/arm/crashglue.S b/debuggerd/crasher/arm/crashglue.S
index 8649056..e4adf40 100644
--- a/debuggerd/crasher/arm/crashglue.S
+++ b/debuggerd/crasher/arm/crashglue.S
@@ -1,6 +1,10 @@
.globl crash1
.type crash1, %function
crash1:
+ .cfi_startproc
+ push {lr}
+ .cfi_def_cfa_offset 4
+ .cfi_rel_offset lr, 0
ldr r0, =0xa5a50000
ldr r1, =0xa5a50001
ldr r2, =0xa5a50002
@@ -15,48 +19,19 @@
ldr r11, =0xa5a50011
ldr r12, =0xa5a50012
-
- fconstd d0, #0
- fconstd d1, #1
- fconstd d2, #2
- fconstd d3, #3
- fconstd d4, #4
- fconstd d5, #5
- fconstd d6, #6
- fconstd d7, #7
- fconstd d8, #8
- fconstd d9, #9
- fconstd d10, #10
- fconstd d11, #11
- fconstd d12, #12
- fconstd d13, #13
- fconstd d14, #14
- fconstd d15, #15
- fconstd d16, #16
- fconstd d17, #17
- fconstd d18, #18
- fconstd d19, #19
- fconstd d20, #20
- fconstd d21, #21
- fconstd d22, #22
- fconstd d23, #23
- fconstd d24, #24
- fconstd d25, #25
- fconstd d26, #26
- fconstd d27, #27
- fconstd d28, #28
- fconstd d29, #29
- fconstd d30, #30
- fconstd d31, #31
-
mov lr, #0
ldr lr, [lr]
b .
+ .cfi_endproc
.globl crashnostack
.type crashnostack, %function
crashnostack:
+ .cfi_startproc
+ mov r1, sp
+ .cfi_def_cfa_register r1
mov sp, #0
mov r0, #0
ldr r0, [r0]
b .
+ .cfi_endproc
diff --git a/debuggerd/crasher/arm64/crashglue.S b/debuggerd/crasher/arm64/crashglue.S
index e58b542..97c824e 100644
--- a/debuggerd/crasher/arm64/crashglue.S
+++ b/debuggerd/crasher/arm64/crashglue.S
@@ -1,6 +1,11 @@
.globl crash1
.type crash1, %function
crash1:
+ .cfi_startproc
+ stp x29, x30, [sp, -16]!
+ .cfi_def_cfa_offset 16
+ .cfi_rel_offset x29, 0
+ .cfi_rel_offset x30, 8
ldr x0, =0xa5a50000
ldr x1, =0xa5a50001
ldr x2, =0xa5a50002
@@ -32,48 +37,20 @@
ldr x28, =0xa5a50028
ldr x29, =0xa5a50029
- fmov d0, -1.0 // -1 is more convincing than 0.
- fmov d1, 1.0
- fmov d2, 2.0
- fmov d3, 3.0
- fmov d4, 4.0
- fmov d5, 5.0
- fmov d6, 6.0
- fmov d7, 7.0
- fmov d8, 8.0
- fmov d9, 9.0
- fmov d10, 10.0
- fmov d11, 11.0
- fmov d12, 12.0
- fmov d13, 13.0
- fmov d14, 14.0
- fmov d15, 15.0
- fmov d16, 16.0
- fmov d17, 17.0
- fmov d18, 18.0
- fmov d19, 19.0
- fmov d20, 20.0
- fmov d21, 21.0
- fmov d22, 22.0
- fmov d23, 23.0
- fmov d24, 24.0
- fmov d25, 25.0
- fmov d26, 26.0
- fmov d27, 27.0
- fmov d28, 28.0
- fmov d29, 29.0
- fmov d30, 30.0
- fmov d31, 31.0
-
mov x30, xzr
ldr x30, [x30]
b .
+ .cfi_endproc
.globl crashnostack
.type crashnostack, %function
crashnostack:
+ .cfi_startproc
+ mov x1, sp
+ .cfi_def_cfa_register x1
mov x0, xzr
add sp, x0, xzr
ldr x0, [x0]
b .
+ .cfi_endproc
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 4eb7382..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';
}
}
@@ -159,11 +159,13 @@
}
noinline void fprintf_null() {
- fprintf(nullptr, "oops");
+ FILE* sneaky_null = nullptr;
+ fprintf(sneaky_null, "oops");
}
noinline void readdir_null() {
- readdir(nullptr);
+ DIR* sneaky_null = nullptr;
+ readdir(sneaky_null);
}
noinline int strlen_null() {
diff --git a/debuggerd/crasher/riscv64/crashglue.S b/debuggerd/crasher/riscv64/crashglue.S
index 47dd93b..42f59b3 100644
--- a/debuggerd/crasher/riscv64/crashglue.S
+++ b/debuggerd/crasher/riscv64/crashglue.S
@@ -1,45 +1,56 @@
-
- .globl crash1
- .globl crashnostack
-
+.globl crash1
crash1:
- li x0,0xdead0000+0
- li x1,0xdead0000+1
- li x2,0xdead0000+2
- li x3,0xdead0000+3
- li x4,0xdead0000+4
- li x5,0xdead0000+5
- li x6,0xdead0000+6
- li x7,0xdead0000+7
- li x8,0xdead0000+8
- li x9,0xdead0000+9
- li x10,0xdead0000+10
- li x11,0xdead0000+11
- li x12,0xdead0000+12
- li x13,0xdead0000+13
- li x14,0xdead0000+14
- li x15,0xdead0000+15
- li x16,0xdead0000+16
- li x17,0xdead0000+17
- li x18,0xdead0000+18
- li x19,0xdead0000+19
- li x20,0xdead0000+20
- li x21,0xdead0000+21
- li x22,0xdead0000+22
- li x23,0xdead0000+23
- li x24,0xdead0000+24
- li x25,0xdead0000+25
- li x26,0xdead0000+26
- li x27,0xdead0000+27
- li x28,0xdead0000+28
- # don't trash the stack otherwise the signal handler won't run
- #li $29,0xdead0000+29
- li x30,0xdead0000+30
- li x31,0xdead0000+31
+ .cfi_startproc
+ addi sp, sp, -16
+ .cfi_def_cfa_offset 16
+ sd ra, 8(sp)
+ .cfi_offset ra, -8
+ li x0,0xa5a50000
+ li x1,0xa5a50001
+ li x2,0xa5a50002
+ li x3,0xa5a50003
+ li x4,0xa5a50004
+ li x5,0xa5a50005
+ li x6,0xa5a50006
+ li x7,0xa5a50007
+ li x8,0xa5a50008
+ li x9,0xa5a50009
+ li x10,0xa5a50010
+ li x11,0xa5a50011
+ li x12,0xa5a50012
+ li x13,0xa5a50013
+ li x14,0xa5a50014
+ li x15,0xa5a50015
+ li x16,0xa5a50016
+ li x17,0xa5a50017
+ li x18,0xa5a50018
+ li x19,0xa5a50019
+ li x20,0xa5a50020
+ li x21,0xa5a50021
+ li x22,0xa5a50022
+ li x23,0xa5a50023
+ li x24,0xa5a50024
+ li x25,0xa5a50025
+ li x26,0xa5a50026
+ li x27,0xa5a50027
+ li x28,0xa5a50028
+ li x29,0xa5a50029
+ li x30,0xa5a50030
+ li x31,0xa5a50031
+
+ li sp, 0
+ ld t2, 0(zero)
j .
+ .cfi_endproc
+.globl crashnostack
crashnostack:
- li sp, 0
+ .cfi_startproc
+ mv t1, sp
+ .cfi_def_cfa_register t1
+ li sp, 0
+ ld t2, 0(zero)
j .
+ .cfi_endproc
diff --git a/debuggerd/crasher/x86/crashglue.S b/debuggerd/crasher/x86/crashglue.S
index 59df432..e8eb3a7 100644
--- a/debuggerd/crasher/x86/crashglue.S
+++ b/debuggerd/crasher/x86/crashglue.S
@@ -1,6 +1,4 @@
.globl crash1
-.globl crashnostack
-
crash1:
movl $0xa5a50000, %eax
movl $0xa5a50001, %ebx
@@ -10,6 +8,11 @@
jmp *%edx
+.globl crashnostack
crashnostack:
- movl $0, %ebp
- jmp *%ebp
+ .cfi_startproc
+ movl %esp, %eax
+ .cfi_def_cfa_register %eax
+ movl $0, %esp
+ movl (%esp), %ebx
+ .cfi_endproc
diff --git a/debuggerd/crasher/x86_64/crashglue.S b/debuggerd/crasher/x86_64/crashglue.S
index 4d2a5c0..8f67214 100644
--- a/debuggerd/crasher/x86_64/crashglue.S
+++ b/debuggerd/crasher/x86_64/crashglue.S
@@ -1,6 +1,4 @@
.globl crash1
-.globl crashnostack
-
crash1:
movl $0xa5a50000, %eax
movl $0xa5a50001, %ebx
@@ -10,6 +8,11 @@
jmp *%rdx
+.globl crashnostack
crashnostack:
- movl $0, %ebp
- jmp *%rbp
+ .cfi_startproc
+ movq %rsp, %rax
+ .cfi_def_cfa_register %rax
+ movq $0, %rsp
+ movq (%rsp), %rbx
+ .cfi_endproc
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index e20e8d9..26726cf 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -41,22 +41,6 @@
_exit(exit_code);
}
-static std::thread spawn_redirect_thread(unique_fd fd) {
- return std::thread([fd{ std::move(fd) }]() {
- while (true) {
- char buf[BUFSIZ];
- ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, sizeof(buf)));
- if (rc <= 0) {
- return;
- }
-
- if (!android::base::WriteFully(STDOUT_FILENO, buf, rc)) {
- return;
- }
- }
- });
-}
-
int main(int argc, char* argv[]) {
if (argc <= 1) usage(0);
if (argc > 3) usage(1);
@@ -107,14 +91,11 @@
}
}
- unique_fd piperead, pipewrite;
- if (!Pipe(&piperead, &pipewrite)) {
- err(1, "failed to create pipe");
+ unique_fd output_fd(fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0));
+ if (output_fd.get() == -1) {
+ err(1, "failed to fcntl dup stdout");
}
-
- std::thread redirect_thread = spawn_redirect_thread(std::move(piperead));
- if (!debuggerd_trigger_dump(proc_info.pid, dump_type, 0, std::move(pipewrite))) {
- redirect_thread.join();
+ if (!debuggerd_trigger_dump(proc_info.pid, dump_type, 0, std::move(output_fd))) {
if (pid == proc_info.pid) {
errx(1, "failed to dump process %d", pid);
} else {
@@ -122,6 +103,5 @@
}
}
- redirect_thread.join();
return 0;
}
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 9c1b136..52c1c25 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <linux/prctl.h>
#include <malloc.h>
+#include <pthread.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/mman.h>
@@ -36,6 +37,7 @@
#include <string>
#include <thread>
+#include <android/dlext.h>
#include <android/fdsan.h>
#include <android/set_abort_message.h>
#include <bionic/malloc.h>
@@ -64,6 +66,7 @@
#include "crash_test.h"
#include "debuggerd/handler.h"
+#include "gtest/gtest.h"
#include "libdebuggerd/utility.h"
#include "protocol.h"
#include "tombstoned/tombstoned.h"
@@ -110,19 +113,6 @@
ASSERT_MATCH(result, \
R"(#\d\d pc [0-9a-f]+\s+ \S+ (\(offset 0x[0-9a-f]+\) )?\()" frame_name R"(\+)");
-// Enable GWP-ASan at the start of this process. GWP-ASan is enabled using
-// process sampling, so we need to ensure we force GWP-ASan on.
-__attribute__((constructor)) static void enable_gwp_asan() {
- android_mallopt_gwp_asan_options_t opts;
- // No, we're not an app, but let's turn ourselves on without sampling.
- // Technically, if someone's using the *.default_app sysprops, they'll adjust
- // our settings, but I don't think this will be common on a device that's
- // running debuggerd_tests.
- opts.desire = android_mallopt_gwp_asan_options_t::Action::TURN_ON_FOR_APP;
- opts.program_name = "";
- android_mallopt(M_INITIALIZE_GWP_ASAN, &opts, sizeof(android_mallopt_gwp_asan_options_t));
-}
-
static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
InterceptStatus* status, DebuggerdDumpType intercept_type) {
intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName,
@@ -310,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 {
@@ -468,76 +441,6 @@
}
#endif
-// Number of iterations required to reliably guarantee a GWP-ASan crash.
-// GWP-ASan's sample rate is not truly nondeterministic, it initialises a
-// thread-local counter at 2*SampleRate, and decrements on each malloc(). Once
-// the counter reaches zero, we provide a sampled allocation. Then, double that
-// figure to allow for left/right allocation alignment, as this is done randomly
-// without bias.
-#define GWP_ASAN_ITERATIONS_TO_ENSURE_CRASH (0x20000)
-
-struct GwpAsanTestParameters {
- size_t alloc_size;
- bool free_before_access;
- int access_offset;
- std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
-};
-
-struct GwpAsanCrasherTest : CrasherTest, testing::WithParamInterface<GwpAsanTestParameters> {};
-
-GwpAsanTestParameters gwp_asan_tests[] = {
- {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0, "Use After Free, 0 bytes into a 7-byte allocation"},
- {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 1, "Use After Free, 1 byte into a 7-byte allocation"},
- {/* alloc_size */ 7, /* free_before_access */ false, /* access_offset */ 16, "Buffer Overflow, 9 bytes right of a 7-byte allocation"},
- {/* alloc_size */ 16, /* free_before_access */ false, /* access_offset */ -1, "Buffer Underflow, 1 byte left of a 16-byte allocation"},
-};
-
-INSTANTIATE_TEST_SUITE_P(GwpAsanTests, GwpAsanCrasherTest, testing::ValuesIn(gwp_asan_tests));
-
-TEST_P(GwpAsanCrasherTest, gwp_asan_uaf) {
- if (mte_supported()) {
- // Skip this test on MTE hardware, as MTE will reliably catch these errors
- // instead of GWP-ASan.
- GTEST_SKIP() << "Skipped on MTE.";
- }
- // Skip this test on HWASan, which will reliably catch test errors as well.
- SKIP_WITH_HWASAN;
-
- GwpAsanTestParameters params = GetParam();
- LogcatCollector logcat_collector;
-
- int intercept_result;
- unique_fd output_fd;
- StartProcess([¶ms]() {
- for (unsigned i = 0; i < GWP_ASAN_ITERATIONS_TO_ENSURE_CRASH; ++i) {
- volatile char* p = reinterpret_cast<volatile char*>(malloc(params.alloc_size));
- if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
- p[params.access_offset] = 42;
- if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
- }
- });
-
- StartIntercept(&output_fd);
- FinishCrasher();
- AssertDeath(SIGSEGV);
- FinishIntercept(&intercept_result);
-
- ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
-
- std::vector<std::string> log_sources(2);
- ConsumeFd(std::move(output_fd), &log_sources[0]);
- logcat_collector.Collect(&log_sources[1]);
-
- for (const auto& result : log_sources) {
- ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
- ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
- if (params.free_before_access) {
- ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
- }
- ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
- }
-}
-
struct SizeParamCrasherTest : CrasherTest, testing::WithParamInterface<size_t> {};
INSTANTIATE_TEST_SUITE_P(Sizes, SizeParamCrasherTest, testing::Values(0, 16, 131072));
@@ -723,7 +626,7 @@
std::string result;
ConsumeFd(std::move(output_fd), &result);
- ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 8 \(SEGV_MTEAERR\), fault addr --------)");
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code [89] \(SEGV_MTE[AS]ERR\), fault addr)");
#else
GTEST_SKIP() << "Requires aarch64";
#endif
@@ -1278,7 +1181,11 @@
static const char* const kDebuggerdSeccompPolicy =
"/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
-static pid_t seccomp_fork_impl(void (*prejail)()) {
+static void setup_jail(minijail* jail) {
+ if (!jail) {
+ LOG(FATAL) << "failed to create minijail";
+ }
+
std::string policy;
if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
PLOG(FATAL) << "failed to read policy file";
@@ -1305,15 +1212,15 @@
PLOG(FATAL) << "failed to seek tmp_fd";
}
- ScopedMinijail jail{minijail_new()};
- if (!jail) {
- LOG(FATAL) << "failed to create minijail";
- }
+ minijail_no_new_privs(jail);
+ minijail_log_seccomp_filter_failures(jail);
+ minijail_use_seccomp_filter(jail);
+ minijail_parse_seccomp_filters_from_fd(jail, tmp_fd.release());
+}
- minijail_no_new_privs(jail.get());
- minijail_log_seccomp_filter_failures(jail.get());
- minijail_use_seccomp_filter(jail.get());
- minijail_parse_seccomp_filters_from_fd(jail.get(), tmp_fd.release());
+static pid_t seccomp_fork_impl(void (*prejail)()) {
+ ScopedMinijail jail{minijail_new()};
+ setup_jail(jail.get());
pid_t result = fork();
if (result == -1) {
@@ -1627,6 +1534,156 @@
AssertDeath(SIGABRT);
}
+struct GwpAsanTestParameters {
+ size_t alloc_size;
+ bool free_before_access;
+ int access_offset;
+ std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
+};
+
+struct GwpAsanCrasherTest
+ : CrasherTest,
+ testing::WithParamInterface<
+ std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
+
+GwpAsanTestParameters gwp_asan_tests[] = {
+ {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
+ "Use After Free, 0 bytes into a 7-byte allocation"},
+ {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
+ "Use After Free, 1 byte into a 15-byte allocation"},
+ {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
+ "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
+ {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
+ "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ GwpAsanTests, GwpAsanCrasherTest,
+ testing::Combine(testing::ValuesIn(gwp_asan_tests),
+ /* recoverable */ testing::Bool(),
+ /* seccomp */ testing::Bool()),
+ [](const testing::TestParamInfo<
+ std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
+ const GwpAsanTestParameters& params = std::get<0>(info.param);
+ std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
+ name += testing::PrintToString(params.alloc_size);
+ name += "Alloc";
+ if (params.access_offset < 0) {
+ name += "Left";
+ name += testing::PrintToString(params.access_offset * -1);
+ } else {
+ name += "Right";
+ name += testing::PrintToString(params.access_offset);
+ }
+ name += "Bytes";
+ if (std::get<1>(info.param)) name += "Recoverable";
+ if (std::get<2>(info.param)) name += "Seccomp";
+ return name;
+ });
+
+TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
+ if (mte_supported()) {
+ // Skip this test on MTE hardware, as MTE will reliably catch these errors
+ // instead of GWP-ASan.
+ GTEST_SKIP() << "Skipped on MTE.";
+ }
+ // Skip this test on HWASan, which will reliably catch test errors as well.
+ SKIP_WITH_HWASAN;
+
+ GwpAsanTestParameters params = std::get<0>(GetParam());
+ bool recoverable = std::get<1>(GetParam());
+ LogcatCollector logcat_collector;
+
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([&recoverable]() {
+ const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
+ "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
+ if (recoverable) {
+ env[3] = "GWP_ASAN_RECOVERABLE=true";
+ }
+ std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
+ test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
+ "DISABLED_run_gwp_asan_test");
+ std::string test_filter = "--gtest_filter=*";
+ test_filter += test_name;
+ std::string this_binary = android::base::GetExecutablePath();
+ const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
+ test_filter.c_str(), nullptr};
+ // We check the crash report from a debuggerd handler and from logcat. The
+ // echo from stdout/stderr of the subprocess trips up atest, because it
+ // doesn't like that two tests started in a row without the first one
+ // finishing (even though the second one is in a subprocess).
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ if (recoverable) {
+ AssertDeath(0);
+ } else {
+ AssertDeath(SIGSEGV);
+ }
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::vector<std::string> log_sources(2);
+ ConsumeFd(std::move(output_fd), &log_sources[0]);
+ logcat_collector.Collect(&log_sources[1]);
+
+ // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
+ // information. Make sure the recovery still works, but the report won't be
+ // hugely useful, it looks like a regular SEGV.
+ bool seccomp = std::get<2>(GetParam());
+ if (!seccomp) {
+ for (const auto& result : log_sources) {
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
+ ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
+ if (params.free_before_access) {
+ ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
+ }
+ ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
+ }
+ }
+}
+
+TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
+ GwpAsanTestParameters params = std::get<0>(GetParam());
+ bool seccomp = std::get<2>(GetParam());
+ if (seccomp) {
+ ScopedMinijail jail{minijail_new()};
+ setup_jail(jail.get());
+ minijail_enter(jail.get());
+ }
+
+ // Use 'volatile' to prevent a very clever compiler eliminating the store.
+ char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
+ if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
+ p[params.access_offset] = 42;
+ if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
+
+ bool recoverable = std::get<1>(GetParam());
+ ASSERT_TRUE(recoverable); // Non-recoverable should have crashed.
+
+ // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
+ // we end with at least one in a different slot), make sure the process still
+ // doesn't crash.
+ p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
+ char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
+ free(static_cast<void*>(const_cast<char*>(p)));
+ free(static_cast<void*>(const_cast<char*>(p2)));
+ *p = 42;
+ *p2 = 42;
+
+ // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
+ // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
+ // coverage does. Thus, skip the atexit handlers.
+ _exit(0);
+}
+
TEST_F(CrasherTest, fdsan_warning_abort_message) {
int intercept_result;
unique_fd output_fd;
@@ -1909,7 +1966,7 @@
ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
}
-static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
+static std::string GetTestLibraryPath() {
std::string test_lib(testing::internal::GetArgvs()[0]);
auto const value = test_lib.find_last_of('/');
if (value == std::string::npos) {
@@ -1917,7 +1974,62 @@
} else {
test_lib = test_lib.substr(0, value + 1) + "./";
}
- test_lib += "libcrash_test.so";
+ return test_lib + "libcrash_test.so";
+}
+
+static void CreateEmbeddedLibrary(int out_fd) {
+ std::string test_lib(GetTestLibraryPath());
+ android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
+ ASSERT_NE(fd.get(), -1);
+ off_t file_size = lseek(fd, 0, SEEK_END);
+ ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
+ std::vector<uint8_t> contents(file_size);
+ ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
+
+ // Put the shared library data at a pagesize() offset.
+ ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
+ ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
+}
+
+TEST_F(CrasherTest, non_zero_offset_in_library) {
+ int intercept_result;
+ unique_fd output_fd;
+ TemporaryFile tf;
+ CreateEmbeddedLibrary(tf.fd);
+ StartProcess([&tf]() {
+ android_dlextinfo extinfo{};
+ extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
+ extinfo.library_fd = tf.fd;
+ extinfo.library_fd_offset = 4 * getpagesize();
+ void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
+ if (handle == nullptr) {
+ _exit(1);
+ }
+ void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
+ if (crash_func == nullptr) {
+ _exit(1);
+ }
+ crash_func();
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGSEGV);
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+ // Verify the crash includes an offset value in the backtrace.
+ std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
+ tf.path, 4 * getpagesize());
+ ASSERT_MATCH(result, match_str);
+}
+
+static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
+ std::string test_lib(GetTestLibraryPath());
*tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
@@ -2309,35 +2421,42 @@
#if defined(__arm__)
asm volatile(
"mov r1, %[base]\n"
- "mov r2, 0\n"
- "str r3, [r2]\n"
+ "mov r2, #0\n"
+ "str r2, [r2]\n"
: [base] "+r"(ptr)
:
- : "r1", "r2", "r3", "memory");
+ : "r1", "r2", "memory");
#elif defined(__aarch64__)
asm volatile(
"mov x1, %[base]\n"
- "mov x2, 0\n"
- "str x3, [x2]\n"
+ "mov x2, #0\n"
+ "str xzr, [x2]\n"
: [base] "+r"(ptr)
:
- : "x1", "x2", "x3", "memory");
+ : "x1", "x2", "memory");
+#elif defined(__riscv)
+ // TODO: x1 is ra (the link register) on riscv64, so this might have
+ // unintended consequences, but we'll need to change the .cfi_escape if so.
+ asm volatile(
+ "mv x1, %[base]\n"
+ "sw zero, 0(zero)\n"
+ : [base] "+r"(ptr)
+ :
+ : "x1", "memory");
#elif defined(__i386__)
asm volatile(
"mov %[base], %%ecx\n"
- "movl $0, %%edi\n"
- "movl 0(%%edi), %%edx\n"
+ "movl $0, 0\n"
: [base] "+r"(ptr)
:
- : "edi", "ecx", "edx", "memory");
+ : "ecx", "memory");
#elif defined(__x86_64__)
asm volatile(
"mov %[base], %%rdx\n"
- "movq 0, %%rdi\n"
- "movq 0(%%rdi), %%rcx\n"
+ "movq $0, 0\n"
: [base] "+r"(ptr)
:
- : "rcx", "rdx", "rdi", "memory");
+ : "rdx", "memory");
#else
#error "Unsupported architecture"
#endif
@@ -2568,3 +2687,103 @@
}
ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
}
+
+const char kLogMessage[] = "Should not see this log message.";
+
+// Verify that the logd process does not read the log.
+TEST_F(CrasherTest, logd_skips_reading_logs) {
+ StartProcess([]() {
+ pthread_setname_np(pthread_self(), "logd");
+ LOG(INFO) << kLogMessage;
+ abort();
+ });
+
+ unique_fd output_fd;
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGABRT);
+ int intercept_result;
+ FinishIntercept(&intercept_result);
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+ // logd should not contain our log message.
+ ASSERT_NOT_MATCH(result, kLogMessage);
+}
+
+// Verify that the logd process does not read the log when the non-main
+// thread crashes.
+TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
+ StartProcess([]() {
+ pthread_setname_np(pthread_self(), "logd");
+ LOG(INFO) << kLogMessage;
+
+ std::thread thread([]() {
+ pthread_setname_np(pthread_self(), "not_logd_thread");
+ // Raise the signal on the side thread.
+ raise_debugger_signal(kDebuggerdTombstone);
+ });
+ thread.join();
+ _exit(0);
+ });
+
+ unique_fd output_fd;
+ StartIntercept(&output_fd, kDebuggerdTombstone);
+ FinishCrasher();
+ AssertDeath(0);
+
+ int intercept_result;
+ FinishIntercept(&intercept_result);
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+ ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
+ ASSERT_NOT_MATCH(result, kLogMessage);
+}
+
+// Disable this test since there is a high liklihood that this would
+// be flaky since it requires 500 messages being in the log.
+TEST_F(CrasherTest, DISABLED_max_log_messages) {
+ StartProcess([]() {
+ for (size_t i = 0; i < 600; i++) {
+ LOG(INFO) << "Message number " << i;
+ }
+ abort();
+ });
+
+ unique_fd output_fd;
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGABRT);
+ int intercept_result;
+ FinishIntercept(&intercept_result);
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+ ASSERT_NOT_MATCH(result, "Message number 99");
+ ASSERT_MATCH(result, "Message number 100");
+ ASSERT_MATCH(result, "Message number 599");
+}
+
+TEST_F(CrasherTest, log_with_newline) {
+ StartProcess([]() {
+ LOG(INFO) << "This line has a newline.\nThis is on the next line.";
+ abort();
+ });
+
+ unique_fd output_fd;
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGABRT);
+ int intercept_result;
+ FinishIntercept(&intercept_result);
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+ ASSERT_MATCH(result, ":\\s*This line has a newline.");
+ ASSERT_MATCH(result, ":\\s*This is on the next line.");
+}
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c64de0e..1e5365d 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -187,27 +187,29 @@
* mutex is being held, so we don't want to use any libc functions that
* could allocate memory or hold a lock.
*/
-static void log_signal_summary(const siginfo_t* info) {
+static void log_signal_summary(const siginfo_t* si) {
char main_thread_name[MAX_TASK_NAME_LEN + 1];
if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
}
- if (info->si_signo == BIONIC_SIGNAL_DEBUGGER) {
+ if (si->si_signo == BIONIC_SIGNAL_DEBUGGER) {
async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for pid %d (%s)", __getpid(),
main_thread_name);
return;
}
- // Many signals don't have an address or sender.
- char addr_desc[32] = ""; // ", fault addr 0x1234"
- if (signal_has_si_addr(info)) {
- async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
- }
+ // Many signals don't have a sender or extra detail, but some do...
pid_t self_pid = __getpid();
char sender_desc[32] = {}; // " from pid 1234, uid 666"
- if (signal_has_sender(info, self_pid)) {
- get_signal_sender(sender_desc, sizeof(sender_desc), info);
+ if (signal_has_sender(si, self_pid)) {
+ get_signal_sender(sender_desc, sizeof(sender_desc), si);
+ }
+ char extra_desc[32] = {}; // ", fault addr 0x1234" or ", syscall 1234"
+ if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
+ async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", syscall %d", si->si_syscall);
+ } else if (signal_has_si_addr(si)) {
+ async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", fault addr %p", si->si_addr);
}
char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
@@ -221,8 +223,8 @@
async_safe_format_log(ANDROID_LOG_FATAL, "libc",
"Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
- info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
- sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
+ si->si_signo, get_signame(si), si->si_code, get_sigcode(si), sender_desc,
+ extra_desc, __gettid(), thread_name, self_pid, main_thread_name);
}
/*
@@ -371,12 +373,31 @@
{.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
};
+ constexpr size_t kHeaderSize = sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t);
+
if (thread_info->process_info.fdsan_table) {
// Dynamic executables always use version 4. There is no need to increment the version number if
// the format changes, because the sender (linker) and receiver (crash_dump) are version locked.
version = 4;
expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
+ static_assert(sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic) ==
+ kHeaderSize + sizeof(thread_info->process_info),
+ "Wire protocol structs do not match the data sent.");
+#define ASSERT_SAME_OFFSET(MEMBER1, MEMBER2) \
+ static_assert(sizeof(CrashInfoHeader) + offsetof(CrashInfoDataDynamic, MEMBER1) == \
+ kHeaderSize + offsetof(debugger_process_info, MEMBER2), \
+ "Wire protocol offset does not match data sent: " #MEMBER1);
+ ASSERT_SAME_OFFSET(fdsan_table_address, fdsan_table);
+ ASSERT_SAME_OFFSET(gwp_asan_state, gwp_asan_state);
+ ASSERT_SAME_OFFSET(gwp_asan_metadata, gwp_asan_metadata);
+ ASSERT_SAME_OFFSET(scudo_stack_depot, scudo_stack_depot);
+ ASSERT_SAME_OFFSET(scudo_region_info, scudo_region_info);
+ ASSERT_SAME_OFFSET(scudo_ring_buffer, scudo_ring_buffer);
+ ASSERT_SAME_OFFSET(scudo_ring_buffer_size, scudo_ring_buffer_size);
+ ASSERT_SAME_OFFSET(recoverable_gwp_asan_crash, recoverable_gwp_asan_crash);
+#undef ASSERT_SAME_OFFSET
+
iovs[3] = {.iov_base = &thread_info->process_info,
.iov_len = sizeof(thread_info->process_info)};
} else {
@@ -384,6 +405,10 @@
version = 1;
expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
+ static_assert(
+ sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic) == kHeaderSize + sizeof(uintptr_t),
+ "Wire protocol structs do not match the data sent.");
+
iovs[3] = {.iov_base = &thread_info->process_info.abort_msg, .iov_len = sizeof(uintptr_t)};
}
errno = 0;
@@ -541,17 +566,40 @@
process_info = g_callbacks.get_process_info();
}
+ gwp_asan_callbacks_t gwp_asan_callbacks = {};
+ if (g_callbacks.get_gwp_asan_callbacks != nullptr) {
+ // GWP-ASan catches use-after-free and heap-buffer-overflow by using PROT_NONE
+ // guard pages, which lead to SEGV. Normally, debuggerd prints a bug report
+ // and the process terminates, but in some cases, we actually want to print
+ // the bug report and let the signal handler return, and restart the process.
+ // In order to do that, we need to disable GWP-ASan's guard pages. The
+ // following callbacks handle this case.
+ gwp_asan_callbacks = g_callbacks.get_gwp_asan_callbacks();
+ if (signal_number == SIGSEGV && signal_has_si_addr(info) &&
+ gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery &&
+ gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report &&
+ gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report &&
+ gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery(info->si_addr)) {
+ gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report(info->si_addr);
+ process_info.recoverable_gwp_asan_crash = true;
+ }
+ }
+
// If sival_int is ~0, it means that the fallback handler has been called
// once before and this function is being called again to dump the stack
// of a specific thread. It is possible that the prctl call might return 1,
// then return 0 in subsequent calls, so check the sival_int to determine if
// the fallback handler should be called first.
- if (si_val == kDebuggerdFallbackSivalUintptrRequestDump ||
- prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
+ bool no_new_privs = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1;
+ if (si_val == kDebuggerdFallbackSivalUintptrRequestDump || no_new_privs) {
// This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
// you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
// ANR trace.
debuggerd_fallback_handler(info, ucontext, process_info.abort_msg);
+ if (no_new_privs && process_info.recoverable_gwp_asan_crash) {
+ gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report(info->si_addr);
+ return;
+ }
resend_signal(info);
return;
}
@@ -625,6 +673,9 @@
// If the signal is fatal, don't unlock the mutex to prevent other crashing threads from
// starting to dump right before our death.
pthread_mutex_unlock(&crash_mutex);
+ } else if (process_info.recoverable_gwp_asan_crash) {
+ gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report(info->si_addr);
+ pthread_mutex_unlock(&crash_mutex);
}
#ifdef __aarch64__
else if (info->si_signo == SIGSEGV &&
@@ -670,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;
@@ -703,3 +754,53 @@
debuggerd_register_handlers(&action);
}
+
+// When debuggerd's signal handler is the first handler called, it's great at
+// handling the recoverable GWP-ASan mode. For apps, sigchain (from libart) is
+// always the first signal handler, and so the following function is what
+// sigchain must call before processing the signal. This allows for processing
+// of a potentially recoverable GWP-ASan crash. If the signal requires GWP-ASan
+// recovery, then dump a report (via the regular debuggerd hanndler), and patch
+// up the allocator, and allow the process to continue (indicated by returning
+// 'true'). If the crash has nothing to do with GWP-ASan, or recovery isn't
+// possible, return 'false'.
+bool debuggerd_handle_signal(int signal_number, siginfo_t* info, void* context) {
+ if (signal_number != SIGSEGV || !signal_has_si_addr(info)) return false;
+
+ if (g_callbacks.get_gwp_asan_callbacks == nullptr) return false;
+ gwp_asan_callbacks_t gwp_asan_callbacks = g_callbacks.get_gwp_asan_callbacks();
+ if (gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery == nullptr ||
+ gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report == nullptr ||
+ gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report == nullptr ||
+ !gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery(info->si_addr)) {
+ return false;
+ }
+
+ // Only dump a crash report for the first GWP-ASan crash. ActivityManager
+ // doesn't like it when an app crashes multiple times, and is even more strict
+ // about an app crashing multiple times in a short time period. While the app
+ // won't crash fully when we do GWP-ASan recovery, ActivityManager still gets
+ // the information about the crash through the DropBoxManager service. If an
+ // app has multiple back-to-back GWP-ASan crashes, this would lead to the app
+ // being killed, which defeats the purpose of having the recoverable mode. To
+ // mitigate against this, only generate a debuggerd crash report for the first
+ // GWP-ASan crash encountered. We still need to do the patching up of the
+ // allocator though, so do that.
+ static pthread_mutex_t first_crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&first_crash_mutex);
+ static bool first_crash = true;
+
+ if (first_crash) {
+ // `debuggerd_signal_handler` will call
+ // `debuggerd_gwp_asan_(pre|post)_crash_report`, so no need to manually call
+ // them here.
+ debuggerd_signal_handler(signal_number, info, context);
+ first_crash = false;
+ } else {
+ gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report(info->si_addr);
+ gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report(info->si_addr);
+ }
+
+ pthread_mutex_unlock(&first_crash_mutex);
+ return true;
+}
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 68b2e67..ebb5372 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -35,7 +35,7 @@
// When updating this data structure, CrashInfoDataDynamic and the code in
// ReadCrashInfo() must also be updated.
-struct debugger_process_info {
+struct __attribute__((packed)) debugger_process_info {
void* abort_msg;
void* fdsan_table;
const gwp_asan::AllocatorState* gwp_asan_state;
@@ -43,16 +43,29 @@
const char* scudo_stack_depot;
const char* scudo_region_info;
const char* scudo_ring_buffer;
+ size_t scudo_ring_buffer_size;
+ bool recoverable_gwp_asan_crash;
};
+// GWP-ASan calbacks to support the recoverable mode. Separate from the
+// debuggerd_callbacks_t because these values aren't available at debuggerd_init
+// time, and have to be synthesized on request.
+typedef struct {
+ bool (*debuggerd_needs_gwp_asan_recovery)(void* fault_addr);
+ void (*debuggerd_gwp_asan_pre_crash_report)(void* fault_addr);
+ void (*debuggerd_gwp_asan_post_crash_report)(void* fault_addr);
+} gwp_asan_callbacks_t;
+
// These callbacks are called in a signal handler, and thus must be async signal safe.
// If null, the callbacks will not be called.
typedef struct {
debugger_process_info (*get_process_info)();
+ gwp_asan_callbacks_t (*get_gwp_asan_callbacks)();
void (*post_dump)();
} debuggerd_callbacks_t;
void debuggerd_init(debuggerd_callbacks_t* callbacks);
+bool debuggerd_handle_signal(int signal_number, siginfo_t* info, void* context);
// DEBUGGER_ACTION_DUMP_TOMBSTONE and DEBUGGER_ACTION_DUMP_BACKTRACE are both
// triggered via BIONIC_SIGNAL_DEBUGGER. The debugger_action_t is sent via si_value
diff --git a/debuggerd/libdebuggerd/gwp_asan.cpp b/debuggerd/libdebuggerd/gwp_asan.cpp
index d8f74e0..26084dc 100644
--- a/debuggerd/libdebuggerd/gwp_asan.cpp
+++ b/debuggerd/libdebuggerd/gwp_asan.cpp
@@ -88,7 +88,7 @@
thread_id_ = thread_info.tid;
// Grab the internal error address, if it exists.
- uintptr_t internal_crash_address = __gwp_asan_get_internal_crash_address(&state_);
+ uintptr_t internal_crash_address = __gwp_asan_get_internal_crash_address(&state_, crash_address_);
if (internal_crash_address) {
crash_address_ = internal_crash_address;
}
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index a51e276..5a2a7ab 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -50,6 +50,7 @@
uintptr_t scudo_stack_depot = 0;
uintptr_t scudo_region_info = 0;
uintptr_t scudo_ring_buffer = 0;
+ size_t scudo_ring_buffer_size = 0;
bool has_fault_address = false;
uintptr_t untagged_fault_address = 0;
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 25b03af..198de37 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -51,7 +51,6 @@
HEADER,
THREAD,
REGISTERS,
- FP_REGISTERS,
BACKTRACE,
MAPS,
MEMORY,
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 5d861f8..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"
@@ -44,28 +45,31 @@
__scudo_get_stack_depot_size());
auto region_info = AllocAndReadFully(process_memory, process_info.scudo_region_info,
__scudo_get_region_info_size());
- auto ring_buffer = AllocAndReadFully(process_memory, process_info.scudo_ring_buffer,
- __scudo_get_ring_buffer_size());
- if (!stack_depot || !region_info || !ring_buffer) {
+ std::unique_ptr<char[]> ring_buffer;
+ if (process_info.scudo_ring_buffer_size != 0) {
+ ring_buffer = AllocAndReadFully(process_memory, process_info.scudo_ring_buffer,
+ process_info.scudo_ring_buffer_size);
+ }
+ if (!stack_depot || !region_info) {
return;
}
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/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 9a565de..7b2e068 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -70,6 +70,9 @@
using android::base::StringPrintf;
+// The maximum number of messages to save in the protobuf per file.
+static constexpr size_t kMaxLogMessages = 500;
+
// Use the demangler from libc++.
extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
@@ -491,8 +494,8 @@
}
static void dump_log_file(Tombstone* tombstone, const char* logger, pid_t pid) {
- logger_list* logger_list =
- android_logger_list_open(android_name_to_log_id(logger), ANDROID_LOG_NONBLOCK, 0, pid);
+ logger_list* logger_list = android_logger_list_open(android_name_to_log_id(logger),
+ ANDROID_LOG_NONBLOCK, kMaxLogMessages, pid);
LogBuffer buffer;
@@ -690,7 +693,14 @@
// Only dump logs on debuggable devices.
if (android::base::GetBoolProperty("ro.debuggable", false)) {
- dump_logcat(&result, main_thread.pid);
+ // Get the thread that corresponds to the main pid of the process.
+ const ThreadInfo& thread = threads.at(main_thread.pid);
+
+ // Do not attempt to dump logs of the logd process because the gathering
+ // of logs can hang until a timeout occurs.
+ if (thread.thread_name != "logd") {
+ dump_logcat(&result, main_thread.pid);
+ }
}
dump_open_fds(&result, open_files);
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 28154a7..8e6abdf 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -176,14 +176,21 @@
build_id = StringPrintf(" (BuildId: %s)", frame.build_id().c_str());
}
- CB(should_log, " #%02d pc %0*" PRIx64 " %s%s%s", index++, pointer_width(tombstone) * 2,
- frame.rel_pc(), frame.file_name().c_str(), function.c_str(), build_id.c_str());
+ std::string line =
+ StringPrintf(" #%02d pc %0*" PRIx64 " %s", index++, pointer_width(tombstone) * 2,
+ frame.rel_pc(), frame.file_name().c_str());
+ if (frame.file_map_offset() != 0) {
+ line += StringPrintf(" (offset 0x%" PRIx64 ")", frame.file_map_offset());
+ }
+ line += function + build_id;
+ CB(should_log, "%s", line.c_str());
}
}
static void print_thread_backtrace(CallbackType callback, const Tombstone& tombstone,
const Thread& thread, bool should_log) {
CBS("");
+ CB(should_log, "%d total frames", thread.current_backtrace().size());
CB(should_log, "backtrace:");
if (!thread.backtrace_note().empty()) {
CB(should_log, " NOTE: %s",
@@ -303,86 +310,8 @@
}
}
-static void print_main_thread(CallbackType callback, const Tombstone& tombstone,
- const Thread& thread) {
+static void print_memory_maps(CallbackType callback, const Tombstone& tombstone) {
int word_size = pointer_width(tombstone);
- print_thread_header(callback, tombstone, thread, true);
-
- const Signal& signal_info = tombstone.signal_info();
- std::string sender_desc;
-
- if (signal_info.has_sender()) {
- sender_desc =
- StringPrintf(" from pid %d, uid %d", signal_info.sender_pid(), signal_info.sender_uid());
- }
-
- if (!tombstone.has_signal_info()) {
- CBL("signal information missing");
- } else {
- std::string fault_addr_desc;
- if (signal_info.has_fault_address()) {
- fault_addr_desc = StringPrintf("0x%0*" PRIx64, 2 * word_size, signal_info.fault_address());
- } else {
- fault_addr_desc = "--------";
- }
-
- CBL("signal %d (%s), code %d (%s%s), fault addr %s", signal_info.number(),
- signal_info.name().c_str(), signal_info.code(), signal_info.code_name().c_str(),
- sender_desc.c_str(), fault_addr_desc.c_str());
- }
-
- if (tombstone.causes_size() == 1) {
- CBL("Cause: %s", tombstone.causes(0).human_readable().c_str());
- }
-
- if (!tombstone.abort_message().empty()) {
- CBL("Abort message: '%s'", tombstone.abort_message().c_str());
- }
-
- print_thread_registers(callback, tombstone, thread, true);
- print_thread_backtrace(callback, tombstone, thread, true);
-
- if (tombstone.causes_size() > 1) {
- CBS("");
- CBL("Note: multiple potential causes for this crash were detected, listing them in decreasing "
- "order of likelihood.");
- }
-
- for (const Cause& cause : tombstone.causes()) {
- if (tombstone.causes_size() > 1) {
- CBS("");
- CBL("Cause: %s", cause.human_readable().c_str());
- }
-
- if (cause.has_memory_error() && cause.memory_error().has_heap()) {
- const HeapObject& heap_object = cause.memory_error().heap();
-
- if (heap_object.deallocation_backtrace_size() != 0) {
- CBS("");
- CBL("deallocated by thread %" PRIu64 ":", heap_object.deallocation_tid());
- print_backtrace(callback, tombstone, heap_object.deallocation_backtrace(), true);
- }
-
- if (heap_object.allocation_backtrace_size() != 0) {
- CBS("");
- CBL("allocated by thread %" PRIu64 ":", heap_object.allocation_tid());
- print_backtrace(callback, tombstone, heap_object.allocation_backtrace(), true);
- }
- }
- }
-
- print_tag_dump(callback, tombstone);
-
- print_thread_memory_dump(callback, tombstone, thread);
-
- CBS("");
-
- // No memory maps to print.
- if (tombstone.memory_mappings().empty()) {
- CBS("No memory maps found");
- return;
- }
-
const auto format_pointer = [word_size](uint64_t ptr) -> std::string {
if (word_size == 8) {
uint64_t top = ptr >> 32;
@@ -397,6 +326,7 @@
StringPrintf("memory map (%d %s):", tombstone.memory_mappings().size(),
tombstone.memory_mappings().size() == 1 ? "entry" : "entries");
+ const Signal& signal_info = tombstone.signal_info();
bool has_fault_address = signal_info.has_fault_address();
uint64_t fault_address = untag_address(signal_info.fault_address());
bool preamble_printed = false;
@@ -456,6 +386,106 @@
}
}
+static void print_main_thread(CallbackType callback, const Tombstone& tombstone,
+ const Thread& thread) {
+ print_thread_header(callback, tombstone, thread, true);
+
+ const Signal& signal_info = tombstone.signal_info();
+ std::string sender_desc;
+
+ if (signal_info.has_sender()) {
+ sender_desc =
+ StringPrintf(" from pid %d, uid %d", signal_info.sender_pid(), signal_info.sender_uid());
+ }
+
+ bool is_async_mte_crash = false;
+ bool is_mte_crash = false;
+ if (!tombstone.has_signal_info()) {
+ CBL("signal information missing");
+ } else {
+ std::string fault_addr_desc;
+ if (signal_info.has_fault_address()) {
+ fault_addr_desc =
+ StringPrintf("0x%0*" PRIx64, 2 * pointer_width(tombstone), signal_info.fault_address());
+ } else {
+ fault_addr_desc = "--------";
+ }
+
+ CBL("signal %d (%s), code %d (%s%s), fault addr %s", signal_info.number(),
+ signal_info.name().c_str(), signal_info.code(), signal_info.code_name().c_str(),
+ sender_desc.c_str(), fault_addr_desc.c_str());
+#ifdef SEGV_MTEAERR
+ is_async_mte_crash = signal_info.number() == SIGSEGV && signal_info.code() == SEGV_MTEAERR;
+ is_mte_crash = is_async_mte_crash ||
+ (signal_info.number() == SIGSEGV && signal_info.code() == SEGV_MTESERR);
+#endif
+ }
+
+ if (tombstone.causes_size() == 1) {
+ CBL("Cause: %s", tombstone.causes(0).human_readable().c_str());
+ }
+
+ if (!tombstone.abort_message().empty()) {
+ CBL("Abort message: '%s'", tombstone.abort_message().c_str());
+ }
+
+ print_thread_registers(callback, tombstone, thread, true);
+ if (is_async_mte_crash) {
+ CBL("Note: This crash is a delayed async MTE crash. Memory corruption has occurred");
+ CBL(" in this process. The stack trace below is the first system call or context");
+ CBL(" switch that was executed after the memory corruption happened.");
+ }
+ print_thread_backtrace(callback, tombstone, thread, true);
+
+ if (tombstone.causes_size() > 1) {
+ CBS("");
+ CBL("Note: multiple potential causes for this crash were detected, listing them in decreasing "
+ "order of likelihood.");
+ }
+
+ for (const Cause& cause : tombstone.causes()) {
+ if (tombstone.causes_size() > 1) {
+ CBS("");
+ CBL("Cause: %s", cause.human_readable().c_str());
+ }
+
+ if (cause.has_memory_error() && cause.memory_error().has_heap()) {
+ const HeapObject& heap_object = cause.memory_error().heap();
+
+ if (heap_object.deallocation_backtrace_size() != 0) {
+ CBS("");
+ CBL("deallocated by thread %" PRIu64 ":", heap_object.deallocation_tid());
+ print_backtrace(callback, tombstone, heap_object.deallocation_backtrace(), true);
+ }
+
+ if (heap_object.allocation_backtrace_size() != 0) {
+ CBS("");
+ CBL("allocated by thread %" PRIu64 ":", heap_object.allocation_tid());
+ print_backtrace(callback, tombstone, heap_object.allocation_backtrace(), true);
+ }
+ }
+ }
+
+ print_tag_dump(callback, tombstone);
+
+ if (is_mte_crash) {
+ CBS("");
+ CBL("Learn more about MTE reports: "
+ "https://source.android.com/docs/security/test/memory-safety/mte-reports");
+ }
+
+ print_thread_memory_dump(callback, tombstone, thread);
+
+ CBS("");
+
+ // No memory maps to print.
+ if (!tombstone.memory_mappings().empty()) {
+ print_memory_maps(callback, tombstone);
+ } else {
+ CBS("No memory maps found");
+ }
+}
+
void print_logs(CallbackType callback, const Tombstone& tombstone, int tail) {
for (const auto& buffer : tombstone.log_buffers()) {
if (tail) {
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 74a1423..d71fc6c 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -47,12 +47,7 @@
using android::base::unique_fd;
bool is_allowed_in_logcat(enum logtype ltype) {
- if ((ltype == HEADER)
- || (ltype == REGISTERS)
- || (ltype == BACKTRACE)) {
- return true;
- }
- return false;
+ return (ltype == HEADER) || (ltype == REGISTERS) || (ltype == BACKTRACE);
}
static bool should_write_to_kmsg() {
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index f33b2f0..b60cf5b 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -98,6 +98,8 @@
uintptr_t scudo_stack_depot;
uintptr_t scudo_region_info;
uintptr_t scudo_ring_buffer;
+ size_t scudo_ring_buffer_size;
+ bool recoverable_gwp_asan_crash;
};
struct __attribute__((__packed__)) CrashInfo {
diff --git a/debuggerd/seccomp_policy/crash_dump.riscv64.policy b/debuggerd/seccomp_policy/crash_dump.riscv64.policy
index 21887ab..281e231 100644
--- a/debuggerd/seccomp_policy/crash_dump.riscv64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.riscv64.policy
@@ -19,12 +19,13 @@
faccessat: 1
recvmsg: 1
recvfrom: 1
+sysinfo: 1
process_vm_readv: 1
tgkill: 1
rt_sigprocmask: 1
rt_sigaction: 1
rt_tgsigqueueinfo: 1
-prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 || arg0 == PR_PAC_RESET_KEYS
+prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
madvise: 1
mprotect: arg2 in 0x1|0x2
munmap: 1
diff --git a/debuggerd/test_permissive_mte/Android.bp b/debuggerd/test_permissive_mte/Android.bp
index 1c09240..d3f7520 100644
--- a/debuggerd/test_permissive_mte/Android.bp
+++ b/debuggerd/test_permissive_mte/Android.bp
@@ -18,6 +18,7 @@
cc_binary {
name: "mte_crash",
+ tidy: false,
srcs: ["mte_crash.cpp"],
sanitize: {
memtag_heap: true,
diff --git a/debuggerd/tombstone_handler.cpp b/debuggerd/tombstone_handler.cpp
new file mode 100644
index 0000000..09df6d9
--- /dev/null
+++ b/debuggerd/tombstone_handler.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 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 "tombstoned/tombstoned.h"
+
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
+#include <cutils/sockets.h>
+#include <linux/vm_sockets.h>
+#include "util.h"
+
+using android::base::unique_fd;
+
+/*
+ Port number that VirtualMachineService listens on connections from the guest VMs.
+ Kep in sync with IVirtualMachineService.aidl
+*/
+const unsigned int VM_TOMBSTONES_SERVICE_PORT = 2000;
+
+static bool is_microdroid() {
+ return android::base::GetProperty("ro.hardware", "") == "microdroid";
+}
+
+static bool connect_tombstone_server_microdroid(unique_fd* text_output_fd,
+ unique_fd* proto_output_fd,
+ DebuggerdDumpType dump_type) {
+ // We do not wait for the property to be set, the default behaviour is not export tombstones.
+ if (!android::base::GetBoolProperty("microdroid_manager.export_tombstones.enabled", false)) {
+ LOG(WARNING) << "exporting tombstones is not enabled";
+ return false;
+ }
+
+ // Microdroid supports handling requests originating from crash_dump which
+ // supports limited dump types. Java traces and incept management are not supported.
+ switch (dump_type) {
+ case kDebuggerdNativeBacktrace:
+ case kDebuggerdTombstone:
+ case kDebuggerdTombstoneProto:
+ break;
+
+ default:
+ LOG(WARNING) << "Requested dump type: " << dump_type << " "
+ << "not supported";
+ }
+
+ int fd1 = TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM, 0));
+ int fd2 = TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM, 0));
+ if (fd1 < 0 || fd2 < 0) {
+ LOG(WARNING) << "Unable to create virtual socket for writing tombstones";
+ return false;
+ }
+
+ unique_fd vsock_output_fd(fd1), vsock_proto_fd(fd2);
+
+ struct sockaddr_vm sa = (struct sockaddr_vm){
+ .svm_family = AF_VSOCK,
+ .svm_port = VM_TOMBSTONES_SERVICE_PORT,
+ .svm_cid = VMADDR_CID_HOST,
+ };
+
+ if (TEMP_FAILURE_RETRY(connect(vsock_output_fd, (struct sockaddr*)&sa, sizeof(sa))) < 0) {
+ PLOG(WARNING) << "Unable to connect to tombstone service in host";
+ return false;
+ }
+
+ if (dump_type == kDebuggerdTombstoneProto) {
+ if (TEMP_FAILURE_RETRY(connect(vsock_proto_fd, (struct sockaddr*)&sa, sizeof(sa))) < 0) {
+ PLOG(WARNING) << "Unable to connect to tombstone service in host";
+ return false;
+ }
+ }
+
+ *text_output_fd = std::move(vsock_output_fd);
+ if (proto_output_fd) {
+ *proto_output_fd = std::move(vsock_proto_fd);
+ }
+ return true;
+}
+
+static bool notify_completion_microdroid(int vsock_out, int vsock_proto) {
+ if (shutdown(vsock_out, SHUT_WR) || shutdown(vsock_proto, SHUT_WR)) return false;
+ return true;
+}
+bool connect_tombstone_server(pid_t pid, unique_fd* tombstoned_socket, unique_fd* text_output_fd,
+ unique_fd* proto_output_fd, DebuggerdDumpType dump_type) {
+ if (is_microdroid()) {
+ return connect_tombstone_server_microdroid(text_output_fd, proto_output_fd, dump_type);
+ }
+ return tombstoned_connect(pid, tombstoned_socket, text_output_fd, proto_output_fd, dump_type);
+}
+
+bool notify_completion(int tombstoned_socket, int vsock_out, int vsock_proto) {
+ if (is_microdroid()) {
+ return notify_completion_microdroid(vsock_out, vsock_proto);
+ }
+ return tombstoned_notify_completion(tombstoned_socket);
+}
diff --git a/debuggerd/tombstone_handler.h b/debuggerd/tombstone_handler.h
new file mode 100644
index 0000000..8726bd3
--- /dev/null
+++ b/debuggerd/tombstone_handler.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 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 <android-base/unique_fd.h>
+#include "dump_type.h"
+
+bool connect_tombstone_server(pid_t pid, android::base::unique_fd* tombstoned_socket,
+ android::base::unique_fd* text_output_fd,
+ android::base::unique_fd* proto_output_fd,
+ DebuggerdDumpType dump_type);
+
+bool notify_completion(int tombstoned_socket, int vsock_out, int vsock_proto);
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 765174b..56cac88 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -170,7 +170,7 @@
"android.hardware.fastboot@1.1",
"android.hardware.fastboot-V1-ndk",
"android.hardware.health@2.0",
- "android.hardware.health-V1-ndk",
+ "android.hardware.health-V2-ndk",
"libasyncio",
"libbase",
"libbinder_ndk",
@@ -196,6 +196,7 @@
"libfastbootshim",
"libsnapshot_cow",
"liblz4",
+ "libzstd",
"libsnapshot_nobinder",
"update_metadata-protos",
"liburing",
@@ -283,14 +284,18 @@
srcs: [
"bootimg_utils.cpp",
+ "fastboot_driver.cpp",
"fastboot.cpp",
+ "filesystem.cpp",
"fs.cpp",
"socket.cpp",
+ "storage.cpp",
+ "super_flash_helper.cpp",
"tcp.cpp",
"udp.cpp",
"util.cpp",
"vendor_boot_img_utils.cpp",
- "fastboot_driver.cpp",
+ "task.cpp",
],
// Only version the final binaries
@@ -372,14 +377,20 @@
defaults: ["fastboot_host_defaults"],
srcs: [
+ "fastboot_driver_test.cpp",
"fastboot_test.cpp",
"socket_mock.cpp",
"socket_test.cpp",
+ "super_flash_helper_test.cpp",
+ "task_test.cpp",
"tcp_test.cpp",
"udp_test.cpp",
],
- static_libs: ["libfastboot"],
+ static_libs: [
+ "libfastboot",
+ "libgmock",
+ ],
target: {
windows: {
@@ -390,6 +401,14 @@
enabled: false,
},
},
+
+ test_suites: ["general-tests"],
+
+ data: [
+ "testdata/super.img",
+ "testdata/super_empty.img",
+ "testdata/system.img",
+ ],
}
cc_test_host {
diff --git a/fastboot/README.md b/fastboot/README.md
index d3b6c1a..63db5c3 100644
--- a/fastboot/README.md
+++ b/fastboot/README.md
@@ -29,20 +29,27 @@
2. Client response with a single packet no greater than 256 bytes.
The first four bytes of the response are "OKAY", "FAIL", "DATA",
- or "INFO". Additional bytes may contain an (ascii) informative
+ "INFO" or "TEXT". Additional bytes may contain an (ascii) informative
message.
a. INFO -> the remaining 252 bytes are an informative message
(providing progress or diagnostic messages). They should
- be displayed and then step #2 repeats
+ be displayed and then step #2 repeats. The print format is:
+ "(bootloader) " + InfoMessagePayload + '\n'
- b. FAIL -> the requested command failed. The remaining 252 bytes
+ b. TEXT -> the remaining 252 bytes are arbitrary. They should
+ be displayed and then step #2 repeats.
+ It differs from info in that no formatting is applied.
+ The payload is printed as-is with no newline at the end.
+ Payload is expected to be NULL terminated.
+
+ c. FAIL -> the requested command failed. The remaining 252 bytes
of the response (if present) provide a textual failure message
to present to the user. Stop.
- c. OKAY -> the requested command completed successfully. Go to #5
+ d. OKAY -> the requested command completed successfully. Go to #5
- d. DATA -> the requested command is ready for the data phase.
+ e. DATA -> the requested command is ready for the data phase.
A DATA response packet will be 12 bytes long, in the form of
DATA00000000 where the 8 digit hexadecimal number represents
the total data size to transfer.
@@ -54,15 +61,17 @@
in the "DATA" response above.
4. Client responds with a single packet no greater than 256 bytes.
- The first four bytes of the response are "OKAY", "FAIL", or "INFO".
- Similar to #2:
+ The first four bytes of the response are "OKAY", "FAIL",
+ "INFO" or "TEXT". Similar to #2:
- a. INFO -> display the remaining 252 bytes and return to #4
+ a. INFO -> display the formatted remaining 252 bytes and return to #4
- b. FAIL -> display the remaining 252 bytes (if present) as a failure
+ b. TEXT -> display the unformatted remaining 252 bytes and return to #4
+
+ c. FAIL -> display the remaining 252 bytes (if present) as a failure
reason and consider the command failed. Stop.
- c. OKAY -> success. Go to #5
+ d. OKAY -> success. Go to #5
5. Success. Stop.
diff --git a/fastboot/TEST_MAPPING b/fastboot/TEST_MAPPING
new file mode 100644
index 0000000..10f3d82
--- /dev/null
+++ b/fastboot/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "fastboot_test"
+ }
+ ]
+}
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 5afeb4f..6b6a982 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -70,11 +70,14 @@
using HidlFastboot = android::hardware::fastboot::V1_1::IFastboot;
using aidl::android::hardware::fastboot::FastbootShim;
auto service_name = IFastboot::descriptor + "/default"s;
- ndk::SpAIBinder binder(AServiceManager_getService(service_name.c_str()));
- std::shared_ptr<IFastboot> fastboot = IFastboot::fromBinder(binder);
- if (fastboot != nullptr) {
- LOG(INFO) << "Using AIDL fastboot service";
- return fastboot;
+ if (AServiceManager_isDeclared(service_name.c_str())) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
+ std::shared_ptr<IFastboot> fastboot = IFastboot::fromBinder(binder);
+ if (fastboot != nullptr) {
+ LOG(INFO) << "Found and using AIDL fastboot service";
+ return fastboot;
+ }
+ LOG(WARNING) << "AIDL fastboot service is declared, but it cannot be retrieved.";
}
LOG(INFO) << "Unable to get AIDL fastboot service, trying HIDL...";
android::sp<HidlFastboot> hidl_fastboot = HidlFastboot::getService();
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 46190f2..30eb7b5 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -44,8 +44,12 @@
#include <unistd.h>
#include <chrono>
+#include <fstream>
#include <functional>
+#include <iostream>
+#include <memory>
#include <regex>
+#include <sstream>
#include <string>
#include <thread>
#include <utility>
@@ -53,6 +57,7 @@
#include <android-base/endian.h>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/parseint.h>
#include <android-base/parsenetaddress.h>
@@ -62,6 +67,7 @@
#include <build/version.h>
#include <libavb/libavb.h>
#include <liblp/liblp.h>
+#include <liblp/super_layout_builder.h>
#include <platform_tools_version.h>
#include <sparse/sparse.h>
#include <ziparchive/zip_archive.h>
@@ -71,6 +77,9 @@
#include "diagnose_usb.h"
#include "fastboot_driver.h"
#include "fs.h"
+#include "storage.h"
+#include "super_flash_helper.h"
+#include "task.h"
#include "tcp.h"
#include "transport.h"
#include "udp.h"
@@ -86,6 +95,8 @@
using namespace std::string_literals;
using namespace std::placeholders;
+#define FASTBOOT_INFO_VERSION 1
+
static const char* serial = nullptr;
static bool g_long_listing = false;
@@ -93,7 +104,6 @@
// libsparse will support INT_MAX, but this results in large allocations, so
// let's keep it at 1GB to avoid memory pressure on the host.
static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024;
-static uint64_t sparse_limit = 0;
static int64_t target_sparse_limit = -1;
static unsigned g_base_addr = 0x10000000;
@@ -106,46 +116,14 @@
fastboot::FastBootDriver* fb = nullptr;
-enum fb_buffer_type {
- FB_BUFFER_FD,
- FB_BUFFER_SPARSE,
-};
-
-struct fastboot_buffer {
- enum fb_buffer_type type;
- void* data;
- int64_t sz;
- unique_fd fd;
- int64_t image_size;
-};
-
-enum class ImageType {
- // Must be flashed for device to boot into the kernel.
- BootCritical,
- // Normal partition to be flashed during "flashall".
- Normal,
- // Partition that is never flashed during "flashall".
- Extra
-};
-
-struct Image {
- const char* nickname;
- const char* img_name;
- const char* sig_name;
- const char* part_name;
- bool optional_if_no_image;
- ImageType type;
- bool IsSecondary() const { return nickname == nullptr; }
-};
-
-static Image images[] = {
+static std::vector<Image> images = {
// clang-format off
{ "boot", "boot.img", "boot.sig", "boot", false, ImageType::BootCritical },
{ "init_boot",
"init_boot.img", "init_boot.sig",
"init_boot",
true, ImageType::BootCritical },
- { nullptr, "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
+ { "", "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
{ "cache", "cache.img", "cache.sig", "cache", true, ImageType::Extra },
{ "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, ImageType::BootCritical },
{ "dts", "dt.img", "dt.sig", "dts", true, ImageType::BootCritical },
@@ -164,7 +142,7 @@
"system_ext.img", "system_ext.sig",
"system_ext",
true, ImageType::Normal },
- { nullptr, "system_other.img", "system.sig", "system", true, ImageType::Normal },
+ { "", "system_other.img", "system.sig", "system", true, ImageType::Normal },
{ "userdata", "userdata.img", "userdata.sig", "userdata", true, ImageType::Extra },
{ "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, ImageType::BootCritical },
{ "vbmeta_system",
@@ -191,7 +169,7 @@
"vendor_kernel_boot.sig",
"vendor_kernel_boot",
true, ImageType::BootCritical },
- { nullptr, "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
+ { "", "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
// clang-format on
};
@@ -211,9 +189,9 @@
return std::string(dir) + "/" + img_name;
}
-static std::string find_item(const std::string& item) {
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && item == images[i].nickname) {
+std::string find_item(const std::string& item) {
+ for (size_t i = 0; i < images.size(); ++i) {
+ if (!images[i].nickname.empty() && item == images[i].nickname) {
return find_item_given_name(images[i].img_name);
}
}
@@ -246,12 +224,8 @@
fprintf(stderr, "(bootloader) %s\n", info.c_str());
}
-static int64_t get_file_size(borrowed_fd fd) {
- struct stat sb;
- if (fstat(fd.get(), &sb) == -1) {
- die("could not get file size");
- }
- return sb.st_size;
+static void TextMessage(const std::string& text) {
+ fprintf(stderr, "%s", text.c_str());
}
bool ReadFileToVector(const std::string& file, std::vector<char>* out) {
@@ -274,12 +248,41 @@
// require matching serial number or device path if requested
// at the command line with the -s option.
if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
- strcmp(local_serial, info->device_path) != 0)) return -1;
+ strcmp(local_serial, info->device_path) != 0))
+ return -1;
return 0;
}
-static int match_fastboot(usb_ifc_info* info) {
- return match_fastboot_with_serial(info, serial);
+static ifc_match_func match_fastboot(const char* local_serial = serial) {
+ return [local_serial](usb_ifc_info* info) -> int {
+ return match_fastboot_with_serial(info, local_serial);
+ };
+}
+
+// output compatible with "adb devices"
+static void PrintDevice(const char* local_serial, const char* status = nullptr,
+ const char* details = nullptr) {
+ if (local_serial == nullptr || strlen(local_serial) == 0) {
+ return;
+ }
+
+ if (g_long_listing) {
+ printf("%-22s", local_serial);
+ } else {
+ printf("%s\t", local_serial);
+ }
+
+ if (status != nullptr && strlen(status) > 0) {
+ printf(" %s", status);
+ }
+
+ if (g_long_listing) {
+ if (details != nullptr && strlen(details) > 0) {
+ printf(" %s", details);
+ }
+ }
+
+ putchar('\n');
}
static int list_devices_callback(usb_ifc_info* info) {
@@ -295,91 +298,235 @@
if (!serial[0]) {
serial = "????????????";
}
- // output compatible with "adb devices"
- if (!g_long_listing) {
- printf("%s\t%s", serial.c_str(), interface.c_str());
- } else {
- printf("%-22s %s", serial.c_str(), interface.c_str());
- if (strlen(info->device_path) > 0) printf(" %s", info->device_path);
- }
- putchar('\n');
+
+ PrintDevice(serial.c_str(), interface.c_str(), info->device_path);
}
return -1;
}
-// Opens a new Transport connected to a device. If |serial| is non-null it will be used to identify
-// a specific device, otherwise the first USB device found will be used.
+Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial) {
+ Socket::Protocol protocol;
+ const char* net_address = nullptr;
+ int port = 0;
+
+ if (android::base::StartsWith(serial, "tcp:")) {
+ protocol = Socket::Protocol::kTcp;
+ net_address = serial.c_str() + strlen("tcp:");
+ port = tcp::kDefaultPort;
+ } else if (android::base::StartsWith(serial, "udp:")) {
+ protocol = Socket::Protocol::kUdp;
+ net_address = serial.c_str() + strlen("udp:");
+ port = udp::kDefaultPort;
+ } else {
+ return Error<FastbootError>(FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX)
+ << "protocol prefix ('tcp:' or 'udp:') is missed: " << serial << ". "
+ << "Expected address format:\n"
+ << "<protocol>:<address>:<port> (tcp:localhost:5554)";
+ }
+
+ std::string error;
+ std::string host;
+ if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
+ return Error<FastbootError>(FastbootError::Type::NETWORK_SERIAL_WRONG_ADDRESS)
+ << "invalid network address '" << net_address << "': " << error;
+ }
+
+ return NetworkSerial{protocol, host, port};
+}
+
+// Opens a new Transport connected to the particular device.
+// arguments:
//
-// If |serial| is non-null but invalid, this exits.
-// Otherwise it blocks until the target is available.
+// local_serial - device to connect (can be a network or usb serial name)
+// wait_for_device - flag indicates whether we need to wait for device
+// announce - flag indicates whether we need to print error to stdout in case
+// we cannot connect to the device
//
// The returned Transport is a singleton, so multiple calls to this function will return the same
// object, and the caller should not attempt to delete the returned Transport.
-static Transport* open_device() {
- bool announce = true;
-
- Socket::Protocol protocol = Socket::Protocol::kTcp;
- std::string host;
- int port = 0;
- if (serial != nullptr) {
- const char* net_address = nullptr;
-
- if (android::base::StartsWith(serial, "tcp:")) {
- protocol = Socket::Protocol::kTcp;
- port = tcp::kDefaultPort;
- net_address = serial + strlen("tcp:");
- } else if (android::base::StartsWith(serial, "udp:")) {
- protocol = Socket::Protocol::kUdp;
- port = udp::kDefaultPort;
- net_address = serial + strlen("udp:");
- }
-
- if (net_address != nullptr) {
- std::string error;
- if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
- die("invalid network address '%s': %s\n", net_address, error.c_str());
- }
- }
- }
+static Transport* open_device(const char* local_serial, bool wait_for_device = true,
+ bool announce = true) {
+ const Result<NetworkSerial, FastbootError> network_serial = ParseNetworkSerial(local_serial);
Transport* transport = nullptr;
while (true) {
- if (!host.empty()) {
+ if (network_serial.ok()) {
std::string error;
- if (protocol == Socket::Protocol::kTcp) {
- transport = tcp::Connect(host, port, &error).release();
- } else if (protocol == Socket::Protocol::kUdp) {
- transport = udp::Connect(host, port, &error).release();
+ if (network_serial->protocol == Socket::Protocol::kTcp) {
+ transport = tcp::Connect(network_serial->address, network_serial->port, &error)
+ .release();
+ } else if (network_serial->protocol == Socket::Protocol::kUdp) {
+ transport = udp::Connect(network_serial->address, network_serial->port, &error)
+ .release();
}
if (transport == nullptr && announce) {
- fprintf(stderr, "error: %s\n", error.c_str());
+ LOG(ERROR) << "error: " << error;
}
+ } else if (network_serial.error().code() ==
+ FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX) {
+ // WRONG_PREFIX is special because it happens when user wants to communicate with USB
+ // device
+ transport = usb_open(match_fastboot(local_serial));
} else {
- transport = usb_open(match_fastboot);
+ Expect(network_serial);
}
if (transport != nullptr) {
return transport;
}
+ if (!wait_for_device) {
+ return nullptr;
+ }
+
if (announce) {
announce = false;
- fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
+ LOG(ERROR) << "< waiting for " << local_serial << ">";
}
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
+static Transport* NetworkDeviceConnected(bool print = false) {
+ Transport* transport = nullptr;
+ Transport* result = nullptr;
+
+ ConnectedDevicesStorage storage;
+ std::set<std::string> devices;
+ if (storage.Exists()) {
+ FileLock lock = storage.Lock();
+ devices = storage.ReadDevices(lock);
+ }
+
+ for (const std::string& device : devices) {
+ transport = open_device(device.c_str(), false, false);
+
+ if (print) {
+ PrintDevice(device.c_str(), transport == nullptr ? "offline" : "fastboot");
+ }
+
+ if (transport != nullptr) {
+ result = transport;
+ }
+ }
+
+ return result;
+}
+
+// Detects the fastboot connected device to open a new Transport.
+// Detecting logic:
+//
+// if serial is provided - try to connect to this particular usb/network device
+// othervise:
+// 1. Check connected usb devices and return the last connected one
+// 2. Check connected network devices and return the last connected one
+// 2. If nothing is connected - wait for any device by repeating p. 1 and 2
+//
+// The returned Transport is a singleton, so multiple calls to this function will return the same
+// object, and the caller should not attempt to delete the returned Transport.
+static Transport* open_device() {
+ if (serial != nullptr) {
+ return open_device(serial);
+ }
+
+ bool announce = true;
+ Transport* transport = nullptr;
+ while (true) {
+ transport = usb_open(match_fastboot(nullptr));
+ if (transport != nullptr) {
+ return transport;
+ }
+
+ transport = NetworkDeviceConnected();
+ if (transport != nullptr) {
+ return transport;
+ }
+
+ if (announce) {
+ announce = false;
+ LOG(ERROR) << "< waiting for any device >";
+ }
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+}
+
+static int Connect(int argc, char* argv[]) {
+ if (argc != 1) {
+ LOG(FATAL) << "connect command requires to receive only 1 argument. Usage:" << std::endl
+ << "fastboot connect [tcp:|udp:host:port]";
+ }
+
+ const char* local_serial = *argv;
+ Expect(ParseNetworkSerial(local_serial));
+
+ const Transport* transport = open_device(local_serial, false);
+ if (transport == nullptr) {
+ return 1;
+ }
+
+ ConnectedDevicesStorage storage;
+ {
+ FileLock lock = storage.Lock();
+ std::set<std::string> devices = storage.ReadDevices(lock);
+ devices.insert(local_serial);
+ storage.WriteDevices(lock, devices);
+ }
+
+ return 0;
+}
+
+static int Disconnect(const char* local_serial) {
+ Expect(ParseNetworkSerial(local_serial));
+
+ ConnectedDevicesStorage storage;
+ {
+ FileLock lock = storage.Lock();
+ std::set<std::string> devices = storage.ReadDevices(lock);
+ devices.erase(local_serial);
+ storage.WriteDevices(lock, devices);
+ }
+
+ return 0;
+}
+
+static int Disconnect() {
+ ConnectedDevicesStorage storage;
+ {
+ FileLock lock = storage.Lock();
+ storage.Clear(lock);
+ }
+
+ return 0;
+}
+
+static int Disconnect(int argc, char* argv[]) {
+ switch (argc) {
+ case 0: {
+ return Disconnect();
+ }
+ case 1: {
+ return Disconnect(*argv);
+ }
+ default:
+ LOG(FATAL) << "disconnect command can receive only 0 or 1 arguments. Usage:"
+ << std::endl
+ << "fastboot disconnect # disconnect all devices" << std::endl
+ << "fastboot disconnect [tcp:|udp:host:port] # disconnect device";
+ }
+
+ return 0;
+}
+
static void list_devices() {
// We don't actually open a USB device here,
// just getting our callback called so we can
// list all the connected devices.
usb_open(list_devices_callback);
+ NetworkDeviceConnected(/* print */ true);
}
-
-static void syntax_error(const char* fmt, ...) {
+void syntax_error(const char* fmt, ...) {
fprintf(stderr, "fastboot: usage: ");
va_list ap;
@@ -532,15 +679,15 @@
std::vector<char> dtb_data;
if (!g_dtb_path.empty()) {
if (g_boot_img_hdr.header_version != 2) {
- die("Argument dtb not supported for boot image header version %d\n",
- g_boot_img_hdr.header_version);
+ die("Argument dtb not supported for boot image header version %d\n",
+ g_boot_img_hdr.header_version);
}
if (!ReadFileToVector(g_dtb_path, &dtb_data)) {
die("cannot load '%s': %s", g_dtb_path.c_str(), strerror(errno));
}
}
- fprintf(stderr,"creating boot image...\n");
+ fprintf(stderr, "creating boot image...\n");
std::vector<char> out;
mkbootimg(kernel_data, ramdisk_data, second_stage_data, dtb_data, g_base_addr, g_boot_img_hdr,
@@ -562,15 +709,15 @@
}
if (zip_entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
- die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
+ die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
}
out->resize(zip_entry.uncompressed_length);
fprintf(stderr, "extracting %s (%zu MB) to RAM...\n", entry_name.c_str(),
out->size() / 1024 / 1024);
- int error = ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()),
- out->size());
+ int error =
+ ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()), out->size());
if (error != 0) die("failed to extract '%s': %s", entry_name.c_str(), ErrorCodeString(error));
return true;
@@ -618,8 +765,8 @@
std::string path_template(make_temporary_template());
int fd = mkstemp(&path_template[0]);
if (fd == -1) {
- die("failed to create temporary file for %s with template %s: %s\n",
- path_template.c_str(), what, strerror(errno));
+ die("failed to create temporary file for %s with template %s: %s\n", path_template.c_str(),
+ what, strerror(errno));
}
unlink(path_template.c_str());
return fd;
@@ -627,7 +774,7 @@
#endif
-static unique_fd unzip_to_file(ZipArchiveHandle zip, const char* entry_name) {
+static unique_fd UnzipToFile(ZipArchiveHandle zip, const char* entry_name) {
unique_fd fd(make_temporary_fd(entry_name));
ZipEntry64 zip_entry;
@@ -673,16 +820,15 @@
std::string var_value;
if (fb->GetVar(var, &var_value) != fastboot::SUCCESS) {
fprintf(stderr, "FAILED\n\n");
- fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(),
- fb->Error().c_str());
+ fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), fb->Error().c_str());
return false;
}
bool match = false;
for (const auto& option : options) {
- if (option == var_value || (option.back() == '*' &&
- !var_value.compare(0, option.length() - 1, option, 0,
- option.length() - 1))) {
+ if (option == var_value ||
+ (option.back() == '*' &&
+ !var_value.compare(0, option.length() - 1, option, 0, option.length() - 1))) {
match = true;
break;
}
@@ -757,8 +903,8 @@
die("device doesn't have required partition %s!", partition_name.c_str());
}
bool known_partition = false;
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && images[i].nickname == partition_name) {
+ for (size_t i = 0; i < images.size(); ++i) {
+ if (!images[i].nickname.empty() && images[i].nickname == partition_name) {
images[i].optional_if_no_image = false;
known_partition = true;
}
@@ -796,9 +942,9 @@
bool met = CheckRequirement(cur_product, name, product, invert, options);
if (!met) {
if (!force_flash) {
- die("requirements not met!");
+ die("requirements not met!");
} else {
- fprintf(stderr, "requirements not met! but proceeding due to --force\n");
+ fprintf(stderr, "requirements not met! but proceeding due to --force\n");
}
}
}
@@ -822,29 +968,34 @@
DisplayVarOrError("Baseband Version.....", "version-baseband");
DisplayVarOrError("Serial Number........", "serialno");
fprintf(stderr, "--------------------------------------------\n");
-
}
-static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
- struct sparse_file* s = sparse_file_import_auto(fd, false, true);
- if (!s) die("cannot sparse read file");
-
+std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) {
if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
- die("invalid max size %" PRId64, max_size);
+ die("invalid max size %" PRId64, max_size);
}
- int files = sparse_file_resparse(s, max_size, nullptr, 0);
- if (files < 0) die("Failed to resparse");
+ const int files = sparse_file_resparse(s, max_size, nullptr, 0);
+ if (files < 0) die("Failed to compute resparse boundaries");
- sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
- if (!out_s) die("Failed to allocate sparse file array");
+ auto temp = std::make_unique<sparse_file*[]>(files);
+ const int rv = sparse_file_resparse(s, max_size, temp.get(), files);
+ if (rv < 0) die("Failed to resparse");
- files = sparse_file_resparse(s, max_size, out_s, files);
- if (files < 0) die("Failed to resparse");
-
+ std::vector<SparsePtr> out_s;
+ for (int i = 0; i < files; i++) {
+ out_s.emplace_back(temp[i], sparse_file_destroy);
+ }
return out_s;
}
+static std::vector<SparsePtr> load_sparse_files(int fd, int64_t max_size) {
+ SparsePtr s(sparse_file_import_auto(fd, false, true), sparse_file_destroy);
+ if (!s) die("cannot sparse read file");
+
+ return resparse_file(s.get(), max_size);
+}
+
static uint64_t get_uint_var(const char* var_name) {
std::string value_str;
if (fb->GetVar(var_name, &value_str) != fastboot::SUCCESS || value_str.empty()) {
@@ -864,8 +1015,8 @@
return value;
}
-static int64_t get_sparse_limit(int64_t size) {
- int64_t limit = sparse_limit;
+int64_t get_sparse_limit(int64_t size, const FlashingPlan* fp) {
+ int64_t limit = int64_t(fp->sparse_limit);
if (limit == 0) {
// Unlimited, so see what the target device's limit is.
// TODO: shouldn't we apply this limit even if you've used -S?
@@ -886,7 +1037,7 @@
return 0;
}
-static bool load_buf_fd(unique_fd fd, struct fastboot_buffer* buf) {
+static bool load_buf_fd(unique_fd fd, struct fastboot_buffer* buf, const FlashingPlan* fp) {
int64_t sz = get_file_size(fd);
if (sz == -1) {
return false;
@@ -894,31 +1045,33 @@
if (sparse_file* s = sparse_file_import(fd.get(), false, false)) {
buf->image_size = sparse_file_len(s, false, false);
+ if (buf->image_size < 0) {
+ LOG(ERROR) << "Could not compute length of sparse file";
+ return false;
+ }
sparse_file_destroy(s);
} else {
buf->image_size = sz;
}
lseek(fd.get(), 0, SEEK_SET);
- int64_t limit = get_sparse_limit(sz);
+ int64_t limit = get_sparse_limit(sz, fp);
buf->fd = std::move(fd);
if (limit) {
- sparse_file** s = load_sparse_files(buf->fd.get(), limit);
- if (s == nullptr) {
+ buf->files = load_sparse_files(buf->fd.get(), limit);
+ if (buf->files.empty()) {
return false;
}
buf->type = FB_BUFFER_SPARSE;
- buf->data = s;
} else {
buf->type = FB_BUFFER_FD;
- buf->data = nullptr;
buf->sz = sz;
}
return true;
}
-static bool load_buf(const char* fname, struct fastboot_buffer* buf) {
+static bool load_buf(const char* fname, struct fastboot_buffer* buf, const FlashingPlan* fp) {
unique_fd fd(TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_BINARY)));
if (fd == -1) {
@@ -934,7 +1087,7 @@
return false;
}
- return load_buf_fd(std::move(fd), buf);
+ return load_buf_fd(std::move(fd), buf, fp);
}
static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_boot) {
@@ -996,18 +1149,17 @@
fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
}
-static bool is_logical(const std::string& partition) {
- std::string value;
- return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes";
+static bool is_vbmeta_partition(const std::string& partition) {
+ return android::base::EndsWith(partition, "vbmeta") ||
+ android::base::EndsWith(partition, "vbmeta_a") ||
+ android::base::EndsWith(partition, "vbmeta_b");
}
-static std::string fb_fix_numeric_var(std::string var) {
- // Some bootloaders (angler, for example), send spurious leading whitespace.
- var = android::base::Trim(var);
- // Some bootloaders (hammerhead, for example) use implicit hex.
- // This code used to use strtol with base 16.
- if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
- return var;
+// Note: this only works in userspace fastboot. In the bootloader, use
+// should_flash_in_userspace().
+bool is_logical(const std::string& partition) {
+ std::string value;
+ return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes";
}
static uint64_t get_partition_size(const std::string& partition) {
@@ -1031,10 +1183,10 @@
}
static void copy_avb_footer(const std::string& partition, struct fastboot_buffer* buf) {
- if (buf->sz < AVB_FOOTER_SIZE) {
+ if (buf->sz < AVB_FOOTER_SIZE || is_logical(partition) ||
+ should_flash_in_userspace(partition)) {
return;
}
-
// If overflows and negative, it should be < buf->sz.
int64_t partition_size = static_cast<int64_t>(get_partition_size(partition));
@@ -1078,43 +1230,36 @@
lseek(buf->fd.get(), 0, SEEK_SET);
}
-static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
-{
- sparse_file** s;
-
- if (partition == "boot" || partition == "boot_a" || partition == "boot_b" ||
- partition == "init_boot" || partition == "init_boot_a" || partition == "init_boot_b") {
- copy_avb_footer(partition, buf);
+void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) {
+ for (size_t i = 0; i < files.size(); i++) {
+ sparse_file* s = files[i].get();
+ int64_t sz = sparse_file_len(s, true, false);
+ if (sz < 0) {
+ LOG(FATAL) << "Could not compute length of sparse image for " << partition;
+ }
+ fb->FlashPartition(partition, s, sz, i + 1, files.size());
}
+}
+
+static void flash_buf(const std::string& partition, struct fastboot_buffer* buf,
+ const bool apply_vbmeta) {
+ copy_avb_footer(partition, buf);
// Rewrite vbmeta if that's what we're flashing and modification has been requested.
if (g_disable_verity || g_disable_verification) {
// The vbmeta partition might have additional prefix if running in virtual machine
// e.g., guest_vbmeta_a.
- if (android::base::EndsWith(partition, "vbmeta") ||
- android::base::EndsWith(partition, "vbmeta_a") ||
- android::base::EndsWith(partition, "vbmeta_b")) {
+ if (apply_vbmeta) {
rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
} else if (!has_vbmeta_partition() &&
(partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
- rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */ );
+ rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */);
}
}
switch (buf->type) {
case FB_BUFFER_SPARSE: {
- std::vector<std::pair<sparse_file*, int64_t>> sparse_files;
- s = reinterpret_cast<sparse_file**>(buf->data);
- while (*s) {
- int64_t sz = sparse_file_len(*s, true, false);
- sparse_files.emplace_back(*s, sz);
- ++s;
- }
-
- for (size_t i = 0; i < sparse_files.size(); ++i) {
- const auto& pair = sparse_files[i];
- fb->FlashPartition(partition, pair.first, pair.second, i + 1, sparse_files.size());
- }
+ flash_partition_files(partition, buf->files);
break;
}
case FB_BUFFER_FD:
@@ -1125,7 +1270,7 @@
}
}
-static std::string get_current_slot() {
+std::string get_current_slot() {
std::string current_slot;
if (fb->GetVar("current-slot", ¤t_slot) != fastboot::SUCCESS) return "";
if (current_slot[0] == '_') current_slot.erase(0, 1);
@@ -1142,15 +1287,15 @@
return count;
}
-static bool supports_AB() {
- return get_slot_count() >= 2;
+bool supports_AB() {
+ return get_slot_count() >= 2;
}
// Given a current slot, this returns what the 'other' slot is.
static std::string get_other_slot(const std::string& current_slot, int count) {
if (count == 0) return "";
- char next = (current_slot[0] - 'a' + 1)%count + 'a';
+ char next = (current_slot[0] - 'a' + 1) % count + 'a';
return std::string(1, next);
}
@@ -1185,17 +1330,17 @@
if (count == 0) die("Device does not support slots");
if (slot == "other") {
- std::string other = get_other_slot( count);
+ std::string other = get_other_slot(count);
if (other == "") {
- die("No known slots");
+ die("No known slots");
}
return other;
}
- if (slot.size() == 1 && (slot[0]-'a' >= 0 && slot[0]-'a' < count)) return slot;
+ if (slot.size() == 1 && (slot[0] - 'a' >= 0 && slot[0] - 'a' < count)) return slot;
fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
fprintf(stderr, "%c\n", (char)(i + 'a'));
}
@@ -1203,7 +1348,7 @@
}
static std::string verify_slot(const std::string& slot) {
- return verify_slot(slot, true);
+ return verify_slot(slot, true);
}
static void do_for_partition(const std::string& part, const std::string& slot,
@@ -1242,8 +1387,8 @@
* partition names. If force_slot is true, it will fail if a slot is specified, and the given
* partition does not support slots.
*/
-static void do_for_partitions(const std::string& part, const std::string& slot,
- const std::function<void(const std::string&)>& func, bool force_slot) {
+void do_for_partitions(const std::string& part, const std::string& slot,
+ const std::function<void(const std::string&)>& func, bool force_slot) {
std::string has_slot;
// |part| can be vendor_boot:default. Query has-slot on the first token only.
auto part_tokens = android::base::Split(part, ":");
@@ -1254,7 +1399,7 @@
slot.c_str());
}
if (has_slot == "yes") {
- for (int i=0; i < get_slot_count(); i++) {
+ for (int i = 0; i < get_slot_count(); i++) {
do_for_partition(part, std::string(1, (char)(i + 'a')), func, force_slot);
}
} else {
@@ -1265,7 +1410,7 @@
}
}
-static bool is_retrofit_device() {
+bool is_retrofit_device() {
std::string value;
if (fb->GetVar("super-partition-name", &value) != fastboot::SUCCESS) {
return false;
@@ -1339,18 +1484,32 @@
return partition;
}
-static void do_flash(const char* pname, const char* fname) {
+void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
+ const FlashingPlan* fp) {
verbose("Do flash %s %s", pname, fname);
struct fastboot_buffer buf;
- if (!load_buf(fname, &buf)) {
+ if (fp && 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));
+ }
+ std::vector<char> signature_data;
+ std::string file_string(fname);
+ if (fp->source->ReadFile(file_string.substr(0, file_string.find('.')) + ".sig",
+ &signature_data)) {
+ fb->Download("signature", signature_data);
+ fb->RawCommand("signature", "installing signature");
+ }
+ } else if (!load_buf(fname, &buf, fp)) {
die("cannot load '%s': %s", fname, strerror(errno));
}
+
if (is_logical(pname)) {
fb->ResizePartition(pname, std::to_string(buf.image_size));
}
std::string flash_pname = repack_ramdisk(pname, &buf);
- flash_buf(flash_pname, &buf);
+ flash_buf(flash_pname, &buf, apply_vbmeta);
}
// Sets slot_override as the active slot. If slot_override is blank,
@@ -1368,19 +1527,19 @@
}
}
-static bool is_userspace_fastboot() {
+bool is_userspace_fastboot() {
std::string value;
return fb->GetVar("is-userspace", &value) == fastboot::SUCCESS && value == "yes";
}
-static void reboot_to_userspace_fastboot() {
+void reboot_to_userspace_fastboot() {
fb->RebootTo("fastboot");
auto* old_transport = fb->set_transport(nullptr);
delete old_transport;
// Give the current connection time to close.
- std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ std::this_thread::sleep_for(std::chrono::seconds(1));
fb->set_transport(open_device());
@@ -1401,120 +1560,279 @@
}
}
-class ImageSource {
- public:
- virtual ~ImageSource() {};
- virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0;
- virtual unique_fd OpenFile(const std::string& name) const = 0;
-};
-
-class FlashAllTool {
- public:
- FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary,
- bool wipe, bool force_flash);
-
- void Flash();
-
- private:
- void CheckRequirements();
- void DetermineSecondarySlot();
- void CollectImages();
- void FlashImages(const std::vector<std::pair<const Image*, std::string>>& images);
- void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf);
- void UpdateSuperPartition();
-
- const ImageSource& source_;
- std::string slot_override_;
- bool skip_secondary_;
- bool wipe_;
- bool force_flash_;
- std::string secondary_slot_;
- std::vector<std::pair<const Image*, std::string>> boot_images_;
- std::vector<std::pair<const Image*, std::string>> os_images_;
-};
-
-FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override,
- bool skip_secondary, bool wipe, bool force_flash)
- : source_(source),
- slot_override_(slot_override),
- skip_secondary_(skip_secondary),
- wipe_(wipe),
- force_flash_(force_flash)
-{
+std::string GetPartitionName(const ImageEntry& entry, const std::string& current_slot) {
+ auto slot = entry.second;
+ if (slot.empty()) {
+ slot = current_slot;
+ }
+ if (slot.empty()) {
+ return entry.first->part_name;
+ }
+ if (slot == "all") {
+ LOG(FATAL) << "Cannot retrieve a singular name when using all slots";
+ }
+ return entry.first->part_name + "_" + slot;
}
+std::unique_ptr<FlashTask> ParseFlashCommand(const FlashingPlan* fp,
+ const std::vector<std::string>& parts) {
+ bool apply_vbmeta = false;
+ std::string slot = fp->slot_override;
+ std::string partition;
+ std::string img_name;
+ for (auto& part : parts) {
+ if (part == "--apply-vbmeta") {
+ apply_vbmeta = true;
+ } else if (part == "--slot-other") {
+ slot = fp->secondary_slot;
+ } else if (partition.empty()) {
+ partition = part;
+ } else if (img_name.empty()) {
+ img_name = part;
+ } else {
+ LOG(ERROR) << "unknown argument" << part
+ << " in fastboot-info.txt. parts: " << android::base::Join(parts, " ");
+ return nullptr;
+ }
+ }
+ if (partition.empty()) {
+ LOG(ERROR) << "partition name not found when parsing fastboot-info.txt. parts: "
+ << android::base::Join(parts, " ");
+ return nullptr;
+ }
+ if (img_name.empty()) {
+ img_name = partition + ".img";
+ }
+ return std::make_unique<FlashTask>(slot, partition, img_name, apply_vbmeta, fp);
+}
+
+std::unique_ptr<RebootTask> ParseRebootCommand(const FlashingPlan* fp,
+ const std::vector<std::string>& parts) {
+ if (parts.empty()) return std::make_unique<RebootTask>(fp);
+ if (parts.size() > 1) {
+ LOG(ERROR) << "unknown arguments in reboot {target} in fastboot-info.txt: "
+ << android::base::Join(parts, " ");
+ return nullptr;
+ }
+ return std::make_unique<RebootTask>(fp, parts[0]);
+}
+
+std::unique_ptr<WipeTask> ParseWipeCommand(const FlashingPlan* fp,
+ const std::vector<std::string>& parts) {
+ if (parts.size() != 1) {
+ LOG(ERROR) << "unknown arguments in erase {partition} in fastboot-info.txt: "
+ << android::base::Join(parts, " ");
+ return nullptr;
+ }
+ return std::make_unique<WipeTask>(fp, parts[0]);
+}
+
+std::unique_ptr<Task> ParseFastbootInfoLine(const FlashingPlan* fp,
+ const std::vector<std::string>& command) {
+ if (command.size() == 0) {
+ return nullptr;
+ }
+ std::unique_ptr<Task> task;
+
+ if (command[0] == "flash") {
+ task = ParseFlashCommand(fp, std::vector<std::string>{command.begin() + 1, command.end()});
+ } else if (command[0] == "reboot") {
+ task = ParseRebootCommand(fp, std::vector<std::string>{command.begin() + 1, command.end()});
+ } else if (command[0] == "update-super" && command.size() == 1) {
+ task = std::make_unique<UpdateSuperTask>(fp);
+ } else if (command[0] == "erase" && command.size() == 2) {
+ task = ParseWipeCommand(fp, std::vector<std::string>{command.begin() + 1, command.end()});
+ }
+ if (!task) {
+ LOG(ERROR) << "unknown command parsing fastboot-info.txt line: "
+ << android::base::Join(command, " ");
+ }
+ return task;
+}
+
+bool AddResizeTasks(const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>* tasks) {
+ // expands "resize-partitions" into individual commands : resize {os_partition_1}, resize
+ // {os_partition_2}, etc.
+ std::vector<std::unique_ptr<Task>> resize_tasks;
+ std::optional<size_t> loc;
+ std::vector<char> contents;
+ if (!fp->source->ReadFile("super_empty.img", &contents)) {
+ return false;
+ }
+ auto metadata = android::fs_mgr::ReadFromImageBlob(contents.data(), contents.size());
+ if (!metadata) {
+ return false;
+ }
+ for (size_t i = 0; i < tasks->size(); i++) {
+ if (auto flash_task = tasks->at(i)->AsFlashTask()) {
+ if (should_flash_in_userspace(*metadata.get(), flash_task->GetPartitionAndSlot())) {
+ if (!loc) {
+ loc = i;
+ }
+ resize_tasks.emplace_back(std::make_unique<ResizeTask>(
+ fp, flash_task->GetPartition(), "0", fp->slot_override));
+ }
+ }
+ }
+ // if no logical partitions (although should never happen since system will always need to be
+ // flashed)
+ if (!loc) {
+ return false;
+ }
+ tasks->insert(tasks->begin() + loc.value(), std::make_move_iterator(resize_tasks.begin()),
+ std::make_move_iterator(resize_tasks.end()));
+ return true;
+}
+
+static bool IsIgnore(const std::vector<std::string>& command) {
+ if (command.size() == 0 || command[0][0] == '#') {
+ return true;
+ }
+ return false;
+}
+
+bool CheckFastbootInfoRequirements(const std::vector<std::string>& command,
+ uint32_t host_tool_version) {
+ if (command.size() != 2) {
+ LOG(ERROR) << "unknown characters in version info in fastboot-info.txt -> "
+ << android::base::Join(command, " ");
+ return false;
+ }
+ if (command[0] != "version") {
+ LOG(ERROR) << "unknown characters in version info in fastboot-info.txt -> "
+ << android::base::Join(command, " ");
+ return false;
+ }
+
+ uint32_t fastboot_info_version;
+ if (!android::base::ParseUint(command[1], &fastboot_info_version)) {
+ LOG(ERROR) << "version number contains non-numeric characters in fastboot-info.txt -> "
+ << android::base::Join(command, " ");
+ return false;
+ }
+
+ LOG(VERBOSE) << "Checking 'fastboot-info.txt version'";
+ if (fastboot_info_version <= host_tool_version) {
+ return true;
+ }
+
+ LOG(ERROR) << "fasboot-info.txt version: " << command[1]
+ << " not compatible with host tool version --> " << host_tool_version;
+ return false;
+}
+
+std::vector<std::unique_ptr<Task>> ParseFastbootInfo(const FlashingPlan* fp,
+ const std::vector<std::string>& file) {
+ std::vector<std::unique_ptr<Task>> tasks;
+ // Get os_partitions that need to be resized
+ for (auto& text : file) {
+ std::vector<std::string> command = android::base::Tokenize(text, " ");
+ if (IsIgnore(command)) {
+ continue;
+ }
+ if (command.size() > 1 && command[0] == "version") {
+ if (!CheckFastbootInfoRequirements(command, FASTBOOT_INFO_VERSION)) {
+ return {};
+ }
+ continue;
+ } else if (command.size() >= 2 && command[0] == "if-wipe") {
+ if (!fp->wants_wipe) {
+ continue;
+ }
+ command.erase(command.begin());
+ }
+ auto task = ParseFastbootInfoLine(fp, command);
+ if (!task) {
+ return {};
+ }
+ tasks.emplace_back(std::move(task));
+ }
+ if (auto flash_super_task = FlashSuperLayoutTask::InitializeFromTasks(fp, tasks)) {
+ auto it = tasks.begin();
+ for (size_t i = 0; i < tasks.size(); i++) {
+ if (auto flash_task = tasks[i]->AsFlashTask()) {
+ if (should_flash_in_userspace(flash_task->GetPartitionAndSlot())) {
+ break;
+ }
+ }
+ if (auto wipe_task = tasks[i]->AsWipeTask()) {
+ break;
+ }
+ it++;
+ }
+ tasks.insert(it, std::move(flash_super_task));
+ } else {
+ if (!AddResizeTasks(fp, &tasks)) {
+ LOG(WARNING) << "Failed to add resize tasks";
+ };
+ }
+ return tasks;
+}
+
+FlashAllTool::FlashAllTool(FlashingPlan* fp) : fp_(fp) {}
+
void FlashAllTool::Flash() {
DumpInfo();
CheckRequirements();
// Change the slot first, so we boot into the correct recovery image when
// using fastbootd.
- if (slot_override_ == "all") {
+ if (fp_->slot_override == "all") {
set_active("a");
} else {
- set_active(slot_override_);
+ set_active(fp_->slot_override);
}
- DetermineSecondarySlot();
- CollectImages();
+ DetermineSlot();
CancelSnapshotIfNeeded();
- // First flash boot partitions. We allow this to happen either in userspace
- // or in bootloader fastboot.
- FlashImages(boot_images_);
-
- // Sync the super partition. This will reboot to userspace fastboot if needed.
- UpdateSuperPartition();
-
- // Resize any logical partition to 0, so each partition is reset to 0
- // extents, and will achieve more optimal allocation.
- for (const auto& [image, slot] : os_images_) {
- auto resize_partition = [](const std::string& partition) -> void {
- if (is_logical(partition)) {
- fb->ResizePartition(partition, "0");
- }
- };
- do_for_partitions(image->part_name, slot, resize_partition, false);
+ tasks_ = CollectTasksFromImageList();
+ for (auto& task : tasks_) {
+ task->Run();
}
-
- // Flash OS images, resizing logical partitions as needed.
- FlashImages(os_images_);
+ return;
}
void FlashAllTool::CheckRequirements() {
std::vector<char> contents;
- if (!source_.ReadFile("android-info.txt", &contents)) {
+ if (!fp_->source->ReadFile("android-info.txt", &contents)) {
die("could not read android-info.txt");
}
- ::CheckRequirements({contents.data(), contents.size()}, force_flash_);
+ ::CheckRequirements({contents.data(), contents.size()}, fp_->force_flash);
}
-void FlashAllTool::DetermineSecondarySlot() {
- if (skip_secondary_) {
+void FlashAllTool::DetermineSlot() {
+ if (fp_->slot_override.empty()) {
+ fp_->current_slot = get_current_slot();
+ } else {
+ fp_->current_slot = fp_->slot_override;
+ }
+
+ if (fp_->skip_secondary) {
return;
}
- if (slot_override_ != "" && slot_override_ != "all") {
- secondary_slot_ = get_other_slot(slot_override_);
+ if (fp_->slot_override != "" && fp_->slot_override != "all") {
+ fp_->secondary_slot = get_other_slot(fp_->slot_override);
} else {
- secondary_slot_ = get_other_slot();
+ fp_->secondary_slot = get_other_slot();
}
- if (secondary_slot_ == "") {
+ if (fp_->secondary_slot == "") {
if (supports_AB()) {
fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
}
- skip_secondary_ = true;
+ fp_->skip_secondary = true;
}
}
void FlashAllTool::CollectImages() {
- for (size_t i = 0; i < arraysize(images); ++i) {
- std::string slot = slot_override_;
+ for (size_t i = 0; i < images.size(); ++i) {
+ std::string slot = fp_->slot_override;
if (images[i].IsSecondary()) {
- if (skip_secondary_) {
+ if (fp_->skip_secondary) {
continue;
}
- slot = secondary_slot_;
+ slot = fp_->secondary_slot;
}
if (images[i].type == ImageType::BootCritical) {
boot_images_.emplace_back(&images[i], slot);
@@ -1524,109 +1842,78 @@
}
}
-void FlashAllTool::FlashImages(const std::vector<std::pair<const Image*, std::string>>& images) {
+std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasksFromImageList() {
+ CollectImages();
+ // First flash boot partitions. We allow this to happen either in userspace
+ // 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_)) {
+ tasks.emplace_back(std::move(flash_super_task));
+ } else {
+ // Sync the super partition. This will reboot to userspace fastboot if needed.
+ tasks.emplace_back(std::make_unique<UpdateSuperTask>(fp_));
+ // Resize any logical partition to 0, so each partition is reset to 0
+ // extents, and will achieve more optimal allocation.
+ for (const auto& [image, slot] : os_images_) {
+ // Retrofit devices have two super partitions, named super_a and super_b.
+ // 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()) {
+ std::string partition_name = image->part_name + "_"s + slot;
+ if (image->IsSecondary() && should_flash_in_userspace(partition_name)) {
+ fp_->fb->DeletePartition(partition_name);
+ }
+ tasks.emplace_back(std::make_unique<DeleteTask>(fp_, partition_name));
+ }
+ tasks.emplace_back(std::make_unique<ResizeTask>(fp_, image->part_name, "0", slot));
+ }
+ }
+ AddFlashTasks(os_images_, tasks);
+ 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) {
fastboot_buffer buf;
- unique_fd fd = source_.OpenFile(image->img_name);
- if (fd < 0 || !load_buf_fd(std::move(fd), &buf)) {
+ unique_fd fd = fp_->source->OpenFile(image->img_name);
+ if (fd < 0 || !load_buf_fd(std::move(fd), &buf, fp_)) {
if (image->optional_if_no_image) {
continue;
}
- die("could not load '%s': %s", image->img_name, strerror(errno));
+ die("could not load '%s': %s", image->img_name.c_str(), strerror(errno));
}
- FlashImage(*image, slot, &buf);
+ tasks.emplace_back(std::make_unique<FlashTask>(slot, image->part_name, image->img_name,
+ is_vbmeta_partition(image->part_name), fp_));
}
}
-void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf) {
- auto flash = [&, this](const std::string& partition_name) {
- std::vector<char> signature_data;
- if (source_.ReadFile(image.sig_name, &signature_data)) {
- fb->Download("signature", signature_data);
- fb->RawCommand("signature", "installing signature");
- }
-
- if (is_logical(partition_name)) {
- fb->ResizePartition(partition_name, std::to_string(buf->image_size));
- }
- flash_buf(partition_name.c_str(), buf);
- };
- do_for_partitions(image.part_name, slot, flash, false);
-}
-
-void FlashAllTool::UpdateSuperPartition() {
- unique_fd fd = source_.OpenFile("super_empty.img");
- if (fd < 0) {
- return;
- }
- if (!is_userspace_fastboot()) {
- reboot_to_userspace_fastboot();
- }
-
- std::string super_name;
- if (fb->GetVar("super-partition-name", &super_name) != fastboot::RetCode::SUCCESS) {
- super_name = "super";
- }
- fb->Download(super_name, fd, get_file_size(fd));
-
- std::string command = "update-super:" + super_name;
- if (wipe_) {
- command += ":wipe";
- }
- fb->RawCommand(command, "Updating super partition");
-
- // Retrofit devices have two super partitions, named super_a and super_b.
- // 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()) {
- for (const auto& [image, slot] : os_images_) {
- std::string partition_name = image->part_name + "_"s + slot;
- if (image->IsSecondary() && is_logical(partition_name)) {
- fb->DeletePartition(partition_name);
- }
- }
- }
-}
-
-class ZipImageSource final : public ImageSource {
- public:
- explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {}
- bool ReadFile(const std::string& name, std::vector<char>* out) const override;
- unique_fd OpenFile(const std::string& name) const override;
-
- private:
- ZipArchiveHandle zip_;
-};
-
bool ZipImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
return UnzipToMemory(zip_, name, out);
}
unique_fd ZipImageSource::OpenFile(const std::string& name) const {
- return unzip_to_file(zip_, name.c_str());
+ return UnzipToFile(zip_, name.c_str());
}
-static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary,
- bool force_flash) {
+static void do_update(const char* filename, FlashingPlan* fp) {
ZipArchiveHandle zip;
int error = OpenArchive(filename, &zip);
if (error != 0) {
die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
}
-
- FlashAllTool tool(ZipImageSource(zip), slot_override, skip_secondary, false, force_flash);
+ ZipImageSource zp = ZipImageSource(zip);
+ fp->source = &zp;
+ fp->wants_wipe = false;
+ FlashAllTool tool(fp);
tool.Flash();
CloseArchive(zip);
}
-class LocalImageSource final : public ImageSource {
- public:
- bool ReadFile(const std::string& name, std::vector<char>* out) const override;
- unique_fd OpenFile(const std::string& name) const override;
-};
-
bool LocalImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
auto path = find_item_given_name(name);
if (path.empty()) {
@@ -1640,9 +1927,10 @@
return unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_BINARY)));
}
-static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe,
- bool force_flash) {
- FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe, force_flash);
+static void do_flashall(FlashingPlan* fp) {
+ LocalImageSource s = LocalImageSource();
+ fp->source = &s;
+ FlashAllTool tool(fp);
tool.Flash();
}
@@ -1683,9 +1971,9 @@
return size;
}
-static void fb_perform_format(const std::string& partition, int skip_if_not_supported,
- const std::string& type_override, const std::string& size_override,
- const unsigned fs_options) {
+void fb_perform_format(const std::string& partition, int skip_if_not_supported,
+ const std::string& type_override, const std::string& size_override,
+ const unsigned fs_options, const FlashingPlan* fp) {
std::string partition_type, partition_size;
struct fastboot_buffer buf;
@@ -1698,8 +1986,8 @@
if (target_sparse_limit > 0 && target_sparse_limit < limit) {
limit = target_sparse_limit;
}
- if (sparse_limit > 0 && sparse_limit < limit) {
- limit = sparse_limit;
+ if (fp->sparse_limit > 0 && fp->sparse_limit < limit) {
+ limit = fp->sparse_limit;
}
if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
@@ -1734,8 +2022,7 @@
fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
return;
}
- die("Formatting is not supported for file system with type '%s'.",
- partition_type.c_str());
+ die("Formatting is not supported for file system with type '%s'.", partition_type.c_str());
}
int64_t size;
@@ -1755,10 +2042,10 @@
if (fd == -1) {
die("Cannot open generated image: %s", strerror(errno));
}
- if (!load_buf_fd(std::move(fd), &buf)) {
+ if (!load_buf_fd(std::move(fd), &buf, fp)) {
die("Cannot read image: %s", strerror(errno));
}
- flash_buf(partition, &buf);
+ flash_buf(partition, &buf, is_vbmeta_partition(partition));
return;
failed:
@@ -1772,7 +2059,7 @@
}
}
-static bool should_flash_in_userspace(const std::string& partition_name) {
+bool should_flash_in_userspace(const std::string& partition_name) {
if (!get_android_product_out()) {
return false;
}
@@ -1784,24 +2071,11 @@
if (!metadata) {
return false;
}
- for (const auto& partition : metadata->partitions) {
- auto candidate = android::fs_mgr::GetPartitionName(partition);
- if (partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED) {
- // On retrofit devices, we don't know if, or whether, the A or B
- // slot has been flashed for dynamic partitions. Instead we add
- // both names to the list as a conservative guess.
- if (candidate + "_a" == partition_name || candidate + "_b" == partition_name) {
- return true;
- }
- } else if (candidate == partition_name) {
- return true;
- }
- }
- return false;
+ return should_flash_in_userspace(*metadata.get(), partition_name);
}
static bool wipe_super(const android::fs_mgr::LpMetadata& metadata, const std::string& slot,
- std::string* message) {
+ std::string* message, const FlashingPlan* fp) {
auto super_device = GetMetadataSuperBlockDevice(metadata);
auto block_size = metadata.geometry.logical_block_size;
auto super_bdev_name = android::fs_mgr::GetBlockDevicePartitionName(*super_device);
@@ -1841,7 +2115,7 @@
auto image_path = temp_dir.path + "/"s + image_name;
auto flash = [&](const std::string& partition_name) {
- do_flash(partition_name.c_str(), image_path.c_str());
+ do_flash(partition_name.c_str(), image_path.c_str(), false, fp);
};
do_for_partitions(partition, slot, flash, force_slot);
@@ -1850,7 +2124,8 @@
return true;
}
-static void do_wipe_super(const std::string& image, const std::string& slot_override) {
+static void do_wipe_super(const std::string& image, const std::string& slot_override,
+ const FlashingPlan* fp) {
if (access(image.c_str(), R_OK) != 0) {
die("Could not read image: %s", image.c_str());
}
@@ -1865,24 +2140,35 @@
}
std::string message;
- if (!wipe_super(*metadata.get(), slot, &message)) {
+ if (!wipe_super(*metadata.get(), slot, &message, fp)) {
die(message);
}
}
+static void FastbootLogger(android::base::LogId /* id */, android::base::LogSeverity severity,
+ const char* /* tag */, const char* /* file */, unsigned int /* line */,
+ const char* message) {
+ switch (severity) {
+ case android::base::INFO:
+ fprintf(stdout, "%s\n", message);
+ break;
+ case android::base::ERROR:
+ fprintf(stderr, "%s\n", message);
+ break;
+ default:
+ verbose("%s\n", message);
+ }
+}
+
+static void FastbootAborter(const char* message) {
+ die("%s", message);
+}
+
int FastBootTool::Main(int argc, char* argv[]) {
- bool wants_wipe = false;
- bool wants_reboot = false;
- bool wants_reboot_bootloader = false;
- bool wants_reboot_recovery = false;
- bool wants_reboot_fastboot = false;
- bool skip_reboot = false;
- bool wants_set_active = false;
- bool skip_secondary = false;
- bool force_flash = false;
- unsigned fs_options = 0;
+ android::base::InitLogging(argv, FastbootLogger, FastbootAborter);
+ std::unique_ptr<FlashingPlan> fp = std::make_unique<FlashingPlan>();
+
int longindex;
- std::string slot_override;
std::string next_active;
g_boot_img_hdr.kernel_addr = 0x00008000;
@@ -1892,34 +2178,35 @@
g_boot_img_hdr.page_size = 2048;
g_boot_img_hdr.dtb_addr = 0x01100000;
- const struct option longopts[] = {
- {"base", required_argument, 0, 0},
- {"cmdline", required_argument, 0, 0},
- {"disable-verification", no_argument, 0, 0},
- {"disable-verity", no_argument, 0, 0},
- {"force", no_argument, 0, 0},
- {"fs-options", required_argument, 0, 0},
- {"header-version", required_argument, 0, 0},
- {"help", no_argument, 0, 'h'},
- {"kernel-offset", required_argument, 0, 0},
- {"os-patch-level", required_argument, 0, 0},
- {"os-version", required_argument, 0, 0},
- {"page-size", required_argument, 0, 0},
- {"ramdisk-offset", required_argument, 0, 0},
- {"set-active", optional_argument, 0, 'a'},
- {"skip-reboot", no_argument, 0, 0},
- {"skip-secondary", no_argument, 0, 0},
- {"slot", required_argument, 0, 0},
- {"tags-offset", required_argument, 0, 0},
- {"dtb", required_argument, 0, 0},
- {"dtb-offset", required_argument, 0, 0},
- {"unbuffered", no_argument, 0, 0},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 0},
- {0, 0, 0, 0}
- };
+ const struct option longopts[] = {{"base", required_argument, 0, 0},
+ {"cmdline", required_argument, 0, 0},
+ {"disable-verification", no_argument, 0, 0},
+ {"disable-verity", no_argument, 0, 0},
+ {"disable-super-optimization", no_argument, 0, 0},
+ {"force", no_argument, 0, 0},
+ {"fs-options", required_argument, 0, 0},
+ {"header-version", required_argument, 0, 0},
+ {"help", no_argument, 0, 'h'},
+ {"kernel-offset", required_argument, 0, 0},
+ {"os-patch-level", required_argument, 0, 0},
+ {"os-version", required_argument, 0, 0},
+ {"page-size", required_argument, 0, 0},
+ {"ramdisk-offset", required_argument, 0, 0},
+ {"set-active", optional_argument, 0, 'a'},
+ {"skip-reboot", no_argument, 0, 0},
+ {"skip-secondary", no_argument, 0, 0},
+ {"slot", required_argument, 0, 0},
+ {"tags-offset", required_argument, 0, 0},
+ {"dtb", required_argument, 0, 0},
+ {"dtb-offset", required_argument, 0, 0},
+ {"unbuffered", no_argument, 0, 0},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 0},
+ {0, 0, 0, 0}};
- serial = getenv("ANDROID_SERIAL");
+ serial = getenv("FASTBOOT_DEVICE");
+ if (!serial)
+ serial = getenv("ANDROID_SERIAL");
int c;
while ((c = getopt_long(argc, argv, "a::hls:S:vw", longopts, &longindex)) != -1) {
@@ -1933,10 +2220,12 @@
g_disable_verification = true;
} else if (name == "disable-verity") {
g_disable_verity = true;
+ } else if (name == "disable-super-optimization") {
+ fp->should_optimize_flash_super = false;
} else if (name == "force") {
- force_flash = true;
+ fp->force_flash = true;
} else if (name == "fs-options") {
- fs_options = ParseFsOption(optarg);
+ fp->fs_options = ParseFsOption(optarg);
} else if (name == "header-version") {
g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0);
} else if (name == "dtb") {
@@ -1953,11 +2242,11 @@
} else if (name == "ramdisk-offset") {
g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16);
} else if (name == "skip-reboot") {
- skip_reboot = true;
+ fp->skip_reboot = true;
} else if (name == "skip-secondary") {
- skip_secondary = true;
+ fp->skip_secondary = true;
} else if (name == "slot") {
- slot_override = optarg;
+ fp->slot_override = optarg;
} else if (name == "dtb-offset") {
g_boot_img_hdr.dtb_addr = strtoul(optarg, 0, 16);
} else if (name == "tags-offset") {
@@ -1966,7 +2255,8 @@
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
} else if (name == "version") {
- fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION, android::build::GetBuildNumber().c_str());
+ fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION,
+ android::build::GetBuildNumber().c_str());
fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str());
return 0;
} else {
@@ -1975,7 +2265,7 @@
} else {
switch (c) {
case 'a':
- wants_set_active = true;
+ fp->wants_set_active = true;
if (optarg) next_active = optarg;
break;
case 'h':
@@ -1987,7 +2277,7 @@
serial = optarg;
break;
case 'S':
- if (!android::base::ParseByteCount(optarg, &sparse_limit)) {
+ if (!android::base::ParseByteCount(optarg, &fp->sparse_limit)) {
die("invalid sparse limit %s", optarg);
}
break;
@@ -1995,7 +2285,7 @@
set_verbose();
break;
case 'w':
- wants_wipe = true;
+ fp->wants_wipe = true;
break;
case '?':
return 1;
@@ -2008,13 +2298,25 @@
argc -= optind;
argv += optind;
- if (argc == 0 && !wants_wipe && !wants_set_active) syntax_error("no command");
+ if (argc == 0 && !fp->wants_wipe && !fp->wants_set_active) syntax_error("no command");
if (argc > 0 && !strcmp(*argv, "devices")) {
list_devices();
return 0;
}
+ if (argc > 0 && !strcmp(*argv, "connect")) {
+ argc -= optind;
+ argv += optind;
+ return Connect(argc, argv);
+ }
+
+ if (argc > 0 && !strcmp(*argv, "disconnect")) {
+ argc -= optind;
+ argv += optind;
+ return Disconnect(argc, argv);
+ }
+
if (argc > 0 && !strcmp(*argv, "help")) {
return show_help();
}
@@ -2024,34 +2326,37 @@
return 1;
}
fastboot::DriverCallbacks driver_callbacks = {
- .prolog = Status,
- .epilog = Epilog,
- .info = InfoMessage,
+ .prolog = Status,
+ .epilog = Epilog,
+ .info = InfoMessage,
+ .text = TextMessage,
};
+
fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false);
fb = &fastboot_driver;
+ fp->fb = &fastboot_driver;
const double start = now();
- if (slot_override != "") slot_override = verify_slot(slot_override);
+ if (fp->slot_override != "") fp->slot_override = verify_slot(fp->slot_override);
if (next_active != "") next_active = verify_slot(next_active, false);
- if (wants_set_active) {
+ if (fp->wants_set_active) {
if (next_active == "") {
- if (slot_override == "") {
+ if (fp->slot_override == "") {
std::string current_slot;
if (fb->GetVar("current-slot", ¤t_slot) == fastboot::SUCCESS) {
if (current_slot[0] == '_') current_slot.erase(0, 1);
next_active = verify_slot(current_slot, false);
} else {
- wants_set_active = false;
+ fp->wants_set_active = false;
}
} else {
- next_active = verify_slot(slot_override, false);
+ next_active = verify_slot(fp->slot_override, false);
}
}
}
-
+ std::vector<std::unique_ptr<Task>> tasks;
std::vector<std::string> args(argv, argv + argc);
while (!args.empty()) {
std::string command = next_arg(&args);
@@ -2063,7 +2368,8 @@
std::string partition = next_arg(&args);
auto erase = [&](const std::string& partition) {
std::string partition_type;
- if (fb->GetVar("partition-type:" + partition, &partition_type) == fastboot::SUCCESS &&
+ if (fb->GetVar("partition-type:" + partition, &partition_type) ==
+ fastboot::SUCCESS &&
fs_get_generator(partition_type) != nullptr) {
fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
partition_type.c_str());
@@ -2071,7 +2377,7 @@
fb->Erase(partition);
};
- do_for_partitions(partition, slot_override, erase, true);
+ do_for_partitions(partition, fp->slot_override, erase, true);
} else if (android::base::StartsWith(command, "format")) {
// Parsing for: "format[:[type][:[size]]]"
// Some valid things:
@@ -2089,9 +2395,10 @@
std::string partition = next_arg(&args);
auto format = [&](const std::string& partition) {
- fb_perform_format(partition, 0, type_override, size_override, fs_options);
+ fb_perform_format(partition, 0, type_override, size_override, fp->fs_options,
+ fp.get());
};
- do_for_partitions(partition, slot_override, format, true);
+ do_for_partitions(partition, fp->slot_override, format, true);
} else if (command == "signature") {
std::string filename = next_arg(&args);
std::vector<char> data;
@@ -2102,31 +2409,19 @@
fb->Download("signature", data);
fb->RawCommand("signature", "installing signature");
} else if (command == FB_CMD_REBOOT) {
- wants_reboot = true;
-
if (args.size() == 1) {
- std::string what = next_arg(&args);
- if (what == "bootloader") {
- wants_reboot = false;
- wants_reboot_bootloader = true;
- } else if (what == "recovery") {
- wants_reboot = false;
- wants_reboot_recovery = true;
- } else if (what == "fastboot") {
- wants_reboot = false;
- wants_reboot_fastboot = true;
- } else {
- syntax_error("unknown reboot target %s", what.c_str());
- }
-
+ std::string reboot_target = next_arg(&args);
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), reboot_target));
+ } else if (!fp->skip_reboot) {
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get()));
}
if (!args.empty()) syntax_error("junk after reboot command");
} else if (command == FB_CMD_REBOOT_BOOTLOADER) {
- wants_reboot_bootloader = true;
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), "bootloader"));
} else if (command == FB_CMD_REBOOT_RECOVERY) {
- wants_reboot_recovery = true;
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), "recovery"));
} else if (command == FB_CMD_REBOOT_FASTBOOT) {
- wants_reboot_fastboot = true;
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), "fastboot"));
} else if (command == FB_CMD_CONTINUE) {
fb->Continue();
} else if (command == FB_CMD_BOOT) {
@@ -2140,7 +2435,6 @@
fb->Boot();
} else if (command == FB_CMD_FLASH) {
std::string pname = next_arg(&args);
-
std::string fname;
if (!args.empty()) {
fname = next_arg(&args);
@@ -2149,20 +2443,8 @@
}
if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
- auto flash = [&](const std::string &partition) {
- if (should_flash_in_userspace(partition) && !is_userspace_fastboot() &&
- !force_flash) {
- die("The partition you are trying to flash is dynamic, and "
- "should be flashed via fastbootd. Please run:\n"
- "\n"
- " fastboot reboot fastboot\n"
- "\n"
- "And try again. If you are intentionally trying to "
- "overwrite a fixed partition, use --force.");
- }
- do_flash(partition.c_str(), fname.c_str());
- };
- do_for_partitions(pname, slot_override, flash, true);
+ FlashTask task(fp->slot_override, pname, fname, is_vbmeta_partition(pname), fp.get());
+ task.Run();
} else if (command == "flash:raw") {
std::string partition = next_arg(&args);
std::string kernel = next_arg(&args);
@@ -2175,26 +2457,32 @@
auto flashraw = [&data](const std::string& partition) {
fb->FlashPartition(partition, data);
};
- do_for_partitions(partition, slot_override, flashraw, true);
+ do_for_partitions(partition, fp->slot_override, flashraw, true);
} else if (command == "flashall") {
- if (slot_override == "all") {
- fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
- do_flashall(slot_override, true, wants_wipe, force_flash);
- } else {
- do_flashall(slot_override, skip_secondary, wants_wipe, force_flash);
+ if (fp->slot_override == "all") {
+ fprintf(stderr,
+ "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ fp->skip_secondary = true;
}
- wants_reboot = true;
+ do_flashall(fp.get());
+
+ if (!fp->skip_reboot) {
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get()));
+ }
} else if (command == "update") {
- bool slot_all = (slot_override == "all");
+ bool slot_all = (fp->slot_override == "all");
if (slot_all) {
- fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ fprintf(stderr,
+ "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
}
std::string filename = "update.zip";
if (!args.empty()) {
filename = next_arg(&args);
}
- do_update(filename.c_str(), slot_override, skip_secondary || slot_all, force_flash);
- wants_reboot = true;
+ do_update(filename.c_str(), fp.get());
+ if (!fp->skip_reboot) {
+ tasks.emplace_back(std::make_unique<RebootTask>(fp.get()));
+ }
} else if (command == FB_CMD_SET_ACTIVE) {
std::string slot = verify_slot(next_arg(&args), false);
fb->SetActive(slot);
@@ -2202,7 +2490,7 @@
std::string filename = next_arg(&args);
struct fastboot_buffer buf;
- if (!load_buf(filename.c_str(), &buf) || buf.type != FB_BUFFER_FD) {
+ if (!load_buf(filename.c_str(), &buf, fp.get()) || buf.type != FB_BUFFER_FD) {
die("cannot load '%s'", filename.c_str());
}
fb->Download(filename, buf.fd.get(), buf.sz);
@@ -2214,10 +2502,9 @@
} else if (command == "flashing") {
if (args.empty()) {
syntax_error("missing 'flashing' command");
- } else if (args.size() == 1 && (args[0] == "unlock" || args[0] == "lock" ||
- args[0] == "unlock_critical" ||
- args[0] == "lock_critical" ||
- args[0] == "get_unlock_ability")) {
+ } else if (args.size() == 1 &&
+ (args[0] == "unlock" || args[0] == "lock" || args[0] == "unlock_critical" ||
+ args[0] == "lock_critical" || args[0] == "get_unlock_ability")) {
do_oem_command("flashing", &args);
} else {
syntax_error("unknown 'flashing' command %s", args[0].c_str());
@@ -2228,11 +2515,13 @@
fb->CreatePartition(partition, size);
} else if (command == FB_CMD_DELETE_PARTITION) {
std::string partition = next_arg(&args);
- fb->DeletePartition(partition);
+ tasks.emplace_back(std::make_unique<DeleteTask>(fp.get(), partition));
} else if (command == FB_CMD_RESIZE_PARTITION) {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
- fb->ResizePartition(partition, size);
+ std::unique_ptr<ResizeTask> resize_task =
+ std::make_unique<ResizeTask>(fp.get(), partition, size, fp->slot_override);
+ resize_task->Run();
} else if (command == "gsi") {
std::string arg = next_arg(&args);
if (arg == "wipe") {
@@ -2249,7 +2538,7 @@
} else {
image = next_arg(&args);
}
- do_wipe_super(image, slot_override);
+ do_wipe_super(image, fp->slot_override, fp.get());
} else if (command == "snapshot-update") {
std::string arg;
if (!args.empty()) {
@@ -2262,43 +2551,30 @@
} else if (command == FB_CMD_FETCH) {
std::string partition = next_arg(&args);
std::string outfile = next_arg(&args);
- do_fetch(partition, slot_override, outfile);
+ do_fetch(partition, fp->slot_override, outfile);
} else {
syntax_error("unknown command %s", command.c_str());
}
}
- if (wants_wipe) {
- if (force_flash) {
+ if (fp->wants_wipe) {
+ if (fp->force_flash) {
CancelSnapshotIfNeeded();
}
- std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
+ std::vector<std::unique_ptr<Task>> wipe_tasks;
+ std::vector<std::string> partitions = {"userdata", "cache", "metadata"};
for (const auto& partition : partitions) {
- std::string partition_type;
- if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
- continue;
- }
- if (partition_type.empty()) continue;
- fb->Erase(partition);
- fb_perform_format(partition, 1, partition_type, "", fs_options);
+ wipe_tasks.emplace_back(std::make_unique<WipeTask>(fp.get(), partition));
}
+ tasks.insert(tasks.begin(), std::make_move_iterator(wipe_tasks.begin()),
+ std::make_move_iterator(wipe_tasks.end()));
}
- if (wants_set_active) {
+ if (fp->wants_set_active) {
fb->SetActive(next_active);
}
- if (wants_reboot && !skip_reboot) {
- fb->Reboot();
- fb->WaitForDisconnect();
- } else if (wants_reboot_bootloader) {
- fb->RebootTo("bootloader");
- fb->WaitForDisconnect();
- } else if (wants_reboot_recovery) {
- fb->RebootTo("recovery");
- fb->WaitForDisconnect();
- } else if (wants_reboot_fastboot) {
- reboot_to_userspace_fastboot();
+ for (auto& task : tasks) {
+ task->Run();
}
-
fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
auto* old_transport = fb->set_transport(nullptr);
@@ -2334,8 +2610,7 @@
unsigned fsOptions = 0;
std::vector<std::string> options = android::base::Split(arg, ",");
- if (options.size() < 1)
- syntax_error("bad options: %s", arg);
+ if (options.size() < 1) syntax_error("bad options: %s", arg);
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == "casefold")
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index c23793a..196bd67 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -25,9 +25,23 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+#pragma once
+
+#include <string>
+#include "fastboot_driver.h"
+#include "fastboot_driver_interface.h"
+#include "filesystem.h"
+#include "super_flash_helper.h"
+#include "task.h"
+#include "util.h"
#include <bootimg.h>
+#include "result.h"
+#include "socket.h"
+#include "util.h"
+#include "ziparchive/zip_archive.h"
+
class FastBootTool {
public:
int Main(int argc, char* argv[]);
@@ -36,3 +50,140 @@
void ParseOsVersion(boot_img_hdr_v1*, const char*);
unsigned ParseFsOption(const char*);
};
+
+enum fb_buffer_type {
+ FB_BUFFER_FD,
+ FB_BUFFER_SPARSE,
+};
+
+struct fastboot_buffer {
+ enum fb_buffer_type type;
+ std::vector<SparsePtr> files;
+ int64_t sz;
+ unique_fd fd;
+ int64_t image_size;
+};
+
+enum class ImageType {
+ // Must be flashed for device to boot into the kernel.
+ BootCritical,
+ // Normal partition to be flashed during "flashall".
+ Normal,
+ // Partition that is never flashed during "flashall".
+ Extra
+};
+
+struct Image {
+ std::string nickname;
+ std::string img_name;
+ std::string sig_name;
+ std::string part_name;
+ bool optional_if_no_image;
+ ImageType type;
+ bool IsSecondary() const { return nickname.empty(); }
+};
+
+using ImageEntry = std::pair<const Image*, std::string>;
+
+struct FlashingPlan {
+ unsigned fs_options = 0;
+ // If the image uses the default slot, or the user specified "all", then
+ // the paired string will be empty. If the image requests a specific slot
+ // (for example, system_other) it is specified instead.
+ ImageSource* source;
+ bool wants_wipe = false;
+ bool skip_reboot = false;
+ bool wants_set_active = false;
+ bool skip_secondary = false;
+ bool force_flash = false;
+ bool should_optimize_flash_super = true;
+ uint64_t sparse_limit = 0;
+
+ std::string slot_override;
+ std::string current_slot;
+ std::string secondary_slot;
+
+ fastboot::IFastBootDriver* fb;
+};
+
+class FlashAllTool {
+ public:
+ FlashAllTool(FlashingPlan* fp);
+
+ void Flash();
+
+ private:
+ void CheckRequirements();
+ void DetermineSlot();
+ 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>> CollectTasksFromImageList();
+
+ std::vector<ImageEntry> boot_images_;
+ std::vector<ImageEntry> os_images_;
+ std::vector<std::unique_ptr<Task>> tasks_;
+
+ FlashingPlan* fp_;
+};
+
+class ZipImageSource final : public ImageSource {
+ public:
+ explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {}
+ bool ReadFile(const std::string& name, std::vector<char>* out) const override;
+ unique_fd OpenFile(const std::string& name) const override;
+
+ private:
+ ZipArchiveHandle zip_;
+};
+
+class LocalImageSource final : public ImageSource {
+ public:
+ bool ReadFile(const std::string& name, std::vector<char>* out) const override;
+ unique_fd OpenFile(const std::string& name) const override;
+};
+
+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,
+ const FlashingPlan* fp);
+void do_for_partitions(const std::string& part, const std::string& slot,
+ const std::function<void(const std::string&)>& func, bool force_slot);
+std::string find_item(const std::string& item);
+void reboot_to_userspace_fastboot();
+void syntax_error(const char* fmt, ...);
+std::string get_current_slot();
+
+// Code for Parsing fastboot-info.txt
+bool CheckFastbootInfoRequirements(const std::vector<std::string>& command,
+ uint32_t host_tool_version);
+std::unique_ptr<FlashTask> ParseFlashCommand(const FlashingPlan* fp,
+ const std::vector<std::string>& parts);
+std::unique_ptr<RebootTask> ParseRebootCommand(const FlashingPlan* fp,
+ const std::vector<std::string>& parts);
+std::unique_ptr<WipeTask> ParseWipeCommand(const FlashingPlan* fp,
+ const std::vector<std::string>& parts);
+std::unique_ptr<Task> ParseFastbootInfoLine(const FlashingPlan* fp,
+ const std::vector<std::string>& command);
+bool AddResizeTasks(const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks);
+std::vector<std::unique_ptr<Task>> ParseFastbootInfo(const FlashingPlan* fp,
+ const std::vector<std::string>& file);
+
+struct NetworkSerial {
+ Socket::Protocol protocol;
+ std::string address;
+ int port;
+};
+
+Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial);
+bool supports_AB();
+std::string GetPartitionName(const ImageEntry& entry, const std::string& current_slot_);
+void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files);
+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_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,
+ const unsigned fs_options, const FlashingPlan* fp);
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index 99a4873..9770ab2 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -64,6 +64,7 @@
prolog_(std::move(driver_callbacks.prolog)),
epilog_(std::move(driver_callbacks.epilog)),
info_(std::move(driver_callbacks.info)),
+ text_(std::move(driver_callbacks.text)),
disable_checks_(no_checks) {}
FastBootDriver::~FastBootDriver() {
@@ -498,6 +499,10 @@
error_ = android::base::StringPrintf("remote: '%s'", status + strlen("FAIL"));
set_response(input.substr(strlen("FAIL")));
return DEVICE_FAIL;
+ } else if (android::base::StartsWith(input, "TEXT")) {
+ text_(input.substr(strlen("TEXT")));
+ // Reset timeout as many more TEXT may come
+ start = std::chrono::steady_clock::now();
} else if (android::base::StartsWith(input, "DATA")) {
std::string tmp = input.substr(strlen("DATA"));
uint32_t num = strtol(tmp.c_str(), 0, 16);
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index bccd668..6ac26ce 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -28,11 +28,12 @@
#pragma once
#include <cstdlib>
#include <deque>
+#include <functional>
#include <limits>
#include <string>
#include <vector>
-#include <android-base/logging.h>
+#include <android-base/endian.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <bootimg.h>
@@ -40,28 +41,21 @@
#include <sparse/sparse.h>
#include "constants.h"
+#include "fastboot_driver_interface.h"
#include "transport.h"
class Transport;
namespace fastboot {
-enum RetCode : int {
- SUCCESS = 0,
- BAD_ARG,
- IO_ERROR,
- BAD_DEV_RESP,
- DEVICE_FAIL,
- TIMEOUT,
-};
-
struct DriverCallbacks {
std::function<void(const std::string&)> prolog = [](const std::string&) {};
std::function<void(int)> epilog = [](int) {};
std::function<void(const std::string&)> info = [](const std::string&) {};
+ std::function<void(const std::string&)> text = [](const std::string&) {};
};
-class FastBootDriver {
+class FastBootDriver : public IFastBootDriver {
friend class FastBootTest;
public:
@@ -76,9 +70,10 @@
RetCode Boot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode Continue(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode CreatePartition(const std::string& partition, const std::string& size);
- RetCode DeletePartition(const std::string& partition);
+ RetCode DeletePartition(const std::string& partition) override;
RetCode Download(const std::string& name, android::base::borrowed_fd fd, size_t size,
- std::string* response = nullptr, std::vector<std::string>* info = nullptr);
+ std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr) override;
RetCode Download(android::base::borrowed_fd fd, size_t size, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode Download(const std::string& name, const std::vector<char>& buf,
@@ -91,16 +86,17 @@
RetCode Download(sparse_file* s, bool use_crc = false, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode Erase(const std::string& partition, std::string* response = nullptr,
- std::vector<std::string>* info = nullptr);
+ std::vector<std::string>* info = nullptr) override;
RetCode Flash(const std::string& partition, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode GetVar(const std::string& key, std::string* val,
- std::vector<std::string>* info = nullptr);
+ std::vector<std::string>* info = nullptr) override;
RetCode GetVarAll(std::vector<std::string>* response);
- RetCode Reboot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
+ RetCode Reboot(std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr) override;
RetCode RebootTo(std::string target, std::string* response = nullptr,
- std::vector<std::string>* info = nullptr);
- RetCode ResizePartition(const std::string& partition, const std::string& size);
+ std::vector<std::string>* info = nullptr) override;
+ RetCode ResizePartition(const std::string& partition, const std::string& size) override;
RetCode SetActive(const std::string& slot, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode Upload(const std::string& outfile, std::string* response = nullptr,
@@ -114,7 +110,7 @@
/* HIGHER LEVEL COMMANDS -- Composed of the commands above */
RetCode FlashPartition(const std::string& partition, const std::vector<char>& data);
RetCode FlashPartition(const std::string& partition, android::base::borrowed_fd fd,
- uint32_t sz);
+ uint32_t sz) override;
RetCode FlashPartition(const std::string& partition, sparse_file* s, uint32_t sz,
size_t current, size_t total);
@@ -126,7 +122,7 @@
void SetInfoCallback(std::function<void(const std::string&)> info);
static const std::string RCString(RetCode rc);
std::string Error();
- RetCode WaitForDisconnect();
+ RetCode WaitForDisconnect() override;
// Note: set_transport will return the previous transport.
Transport* set_transport(Transport* transport);
@@ -168,6 +164,7 @@
std::function<void(const std::string&)> prolog_;
std::function<void(int)> epilog_;
std::function<void(const std::string&)> info_;
+ std::function<void(const std::string&)> text_;
bool disable_checks_;
};
diff --git a/fastboot/fastboot_driver_interface.h b/fastboot/fastboot_driver_interface.h
new file mode 100644
index 0000000..795938f
--- /dev/null
+++ b/fastboot/fastboot_driver_interface.h
@@ -0,0 +1,59 @@
+//
+// 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 "android-base/unique_fd.h"
+
+class Transport;
+
+namespace fastboot {
+
+enum RetCode : int {
+ SUCCESS = 0,
+ BAD_ARG,
+ IO_ERROR,
+ BAD_DEV_RESP,
+ DEVICE_FAIL,
+ TIMEOUT,
+};
+
+class IFastBootDriver {
+ public:
+ RetCode virtual FlashPartition(const std::string& partition, android::base::borrowed_fd fd,
+ uint32_t sz) = 0;
+ RetCode virtual DeletePartition(const std::string& partition) = 0;
+ RetCode virtual WaitForDisconnect() = 0;
+ RetCode virtual Reboot(std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr) = 0;
+
+ RetCode virtual RebootTo(std::string target, std::string* response = nullptr,
+ 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 Download(const std::string& name, android::base::borrowed_fd fd, size_t size,
+ std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr) = 0;
+ RetCode virtual RawCommand(const std::string& cmd, const std::string& message,
+ std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr, int* dsize = nullptr) = 0;
+ RetCode virtual ResizePartition(const std::string& partition, const std::string& size) = 0;
+ RetCode virtual Erase(const std::string& partition, std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr) = 0;
+ virtual ~IFastBootDriver() = default;
+};
+} // namespace fastboot
\ No newline at end of file
diff --git a/fastboot/fastboot_driver_mock.h b/fastboot/fastboot_driver_mock.h
new file mode 100644
index 0000000..d2a123b
--- /dev/null
+++ b/fastboot/fastboot_driver_mock.h
@@ -0,0 +1,50 @@
+//
+// 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 <gmock/gmock.h>
+#include "fastboot_driver_interface.h"
+
+namespace fastboot {
+
+class MockFastbootDriver : public IFastBootDriver {
+ public:
+ MOCK_METHOD(RetCode, FlashPartition, (const std::string&, android::base::borrowed_fd, uint32_t),
+ (override));
+ MOCK_METHOD(RetCode, DeletePartition, (const std::string&), (override));
+ 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, 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*),
+ (override));
+ MOCK_METHOD(RetCode, ResizePartition, (const std::string&, const std::string&), (override));
+ MOCK_METHOD(RetCode, Erase, (const std::string&, std::string*, std::vector<std::string>*),
+ (override));
+ MOCK_METHOD(RetCode, WaitForDisconnect, (), (override));
+};
+
+} // namespace fastboot
\ No newline at end of file
diff --git a/fastboot/fastboot_driver_test.cpp b/fastboot/fastboot_driver_test.cpp
new file mode 100644
index 0000000..6f6cf8c
--- /dev/null
+++ b/fastboot/fastboot_driver_test.cpp
@@ -0,0 +1,95 @@
+//
+// 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 "fastboot_driver.h"
+
+#include <optional>
+
+#include <gtest/gtest.h>
+#include "mock_transport.h"
+
+using namespace ::testing;
+using namespace fastboot;
+
+class DriverTest : public ::testing::Test {
+ protected:
+ InSequence s_;
+};
+
+TEST_F(DriverTest, GetVar) {
+ MockTransport transport;
+ FastBootDriver driver(&transport);
+
+ EXPECT_CALL(transport, Write(_, _))
+ .With(AllArgs(RawData("getvar:version")))
+ .WillOnce(ReturnArg<1>());
+ EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY0.4")));
+
+ std::string output;
+ ASSERT_EQ(driver.GetVar("version", &output), SUCCESS) << driver.Error();
+ ASSERT_EQ(output, "0.4");
+}
+
+TEST_F(DriverTest, InfoMessage) {
+ MockTransport transport;
+ FastBootDriver driver(&transport);
+
+ EXPECT_CALL(transport, Write(_, _))
+ .With(AllArgs(RawData("oem dmesg")))
+ .WillOnce(ReturnArg<1>());
+ EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("INFOthis is an info line")));
+ EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY")));
+
+ std::vector<std::string> info;
+ ASSERT_EQ(driver.RawCommand("oem dmesg", "", nullptr, &info), SUCCESS) << driver.Error();
+ ASSERT_EQ(info.size(), size_t(1));
+ ASSERT_EQ(info[0], "this is an info line");
+}
+
+TEST_F(DriverTest, TextMessage) {
+ MockTransport transport;
+ std::string text;
+
+ DriverCallbacks callbacks{[](const std::string&) {}, [](int) {}, [](const std::string&) {},
+ [&text](const std::string& extra_text) { text += extra_text; }};
+
+ FastBootDriver driver(&transport, callbacks);
+
+ EXPECT_CALL(transport, Write(_, _))
+ .With(AllArgs(RawData("oem trusty runtest trusty.hwaes.bench")))
+ .WillOnce(ReturnArg<1>());
+ EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("TEXTthis is a text line")));
+ EXPECT_CALL(transport, Read(_, _))
+ .WillOnce(Invoke(
+ CopyData("TEXT, albeit very long and split over multiple TEXT messages.")));
+ EXPECT_CALL(transport, Read(_, _))
+ .WillOnce(Invoke(CopyData("TEXT Indeed we can do that now with a TEXT message whenever "
+ "we feel like it.")));
+ EXPECT_CALL(transport, Read(_, _))
+ .WillOnce(Invoke(CopyData("TEXT Isn't that truly super cool?")));
+
+ EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY")));
+
+ std::vector<std::string> info;
+ ASSERT_EQ(driver.RawCommand("oem trusty runtest trusty.hwaes.bench", "", nullptr, &info),
+ SUCCESS)
+ << driver.Error();
+ ASSERT_EQ(text,
+ "this is a text line"
+ ", albeit very long and split over multiple TEXT messages."
+ " Indeed we can do that now with a TEXT message whenever we feel like it."
+ " Isn't that truly super cool?");
+}
diff --git a/fastboot/fastboot_test.cpp b/fastboot/fastboot_test.cpp
index 9c3ab6e..1863e95 100644
--- a/fastboot/fastboot_test.cpp
+++ b/fastboot/fastboot_test.cpp
@@ -16,6 +16,7 @@
#include "fastboot.h"
+#include <android-base/logging.h>
#include <gtest/gtest.h>
TEST(FastBoot, ParseOsPatchLevel) {
@@ -201,3 +202,59 @@
// No spaces allowed before between require-for-product and :.
ParseRequirementLineTestMalformed("require-for-product :");
}
+
+static void ParseNetworkSerialTest(const std::string& description, const std::string& serial,
+ const std::string& expected_address,
+ const Socket::Protocol expected_protocol,
+ const int expected_port) {
+ const Result<NetworkSerial, FastbootError> parsed = ParseNetworkSerial(serial);
+
+ ASSERT_RESULT_OK(parsed) << description;
+
+ const NetworkSerial network_serial = parsed.value();
+ EXPECT_EQ(network_serial.address, expected_address) << description;
+ EXPECT_EQ(network_serial.protocol, expected_protocol) << description;
+ EXPECT_EQ(network_serial.port, expected_port) << description;
+}
+
+static void ParseNetworkSerialNegativeTest(const std::string& description,
+ const std::string& serial,
+ const FastbootError::Type expected_error) {
+ const Result<NetworkSerial, FastbootError> parsed = ParseNetworkSerial(serial);
+
+ EXPECT_FALSE(parsed.ok()) << description;
+ EXPECT_EQ(parsed.error().code(), expected_error) << description;
+}
+
+TEST(FastBoot, ParseNetworkSerial) {
+ ParseNetworkSerialTest("tcp IPv4 parsed", "tcp:192.168.1.0", "192.168.1.0",
+ Socket::Protocol::kTcp, 5554);
+
+ ParseNetworkSerialTest("udp IPv4 parsed", "udp:192.168.1.0", "192.168.1.0",
+ Socket::Protocol::kUdp, 5554);
+
+ ParseNetworkSerialTest("port parsed", "udp:192.168.1.0:9999", "192.168.1.0",
+ Socket::Protocol::kUdp, 9999);
+
+ ParseNetworkSerialTest("IPv6 parsed", "tcp:2001:db8:3333:4444:5555:6666:7777:8888",
+ "2001:db8:3333:4444:5555:6666:7777:8888", Socket::Protocol::kTcp, 5554);
+
+ ParseNetworkSerialTest("empty IPv6 parsed", "tcp:::", "::", Socket::Protocol::kTcp, 5554);
+
+ ParseNetworkSerialNegativeTest("wrong prefix", "tcpa:192.168.1.0",
+ FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX);
+
+ ParseNetworkSerialNegativeTest("no prefix", "192.168.1.0",
+ FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX);
+
+ ParseNetworkSerialNegativeTest("wrong port", "tcp:192.168.1.0:-1",
+ FastbootError::Type::NETWORK_SERIAL_WRONG_ADDRESS);
+}
+
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::base::InitLogging(argv);
+ android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/fastboot/filesystem.cpp b/fastboot/filesystem.cpp
new file mode 100644
index 0000000..94fde8e
--- /dev/null
+++ b/fastboot/filesystem.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+#include <android-base/utf8.h>
+#include <direct.h>
+#include <shlobj.h>
+#else
+#include <pwd.h>
+#endif
+
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include "filesystem.h"
+
+namespace {
+
+int LockFile(int fd) {
+#ifdef _WIN32
+ HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ OVERLAPPED overlapped = {};
+ const BOOL locked =
+ LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped);
+ return locked ? 0 : -1;
+#else
+ return flock(fd, LOCK_EX);
+#endif
+}
+
+} // namespace
+
+// inspired by adb implementation:
+// cs.android.com/android/platform/superproject/+/master:packages/modules/adb/adb_utils.cpp;l=275
+std::string GetHomeDirPath() {
+#ifdef _WIN32
+ WCHAR path[MAX_PATH];
+ const HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path);
+ if (FAILED(hr)) {
+ return {};
+ }
+ std::string home_str;
+ if (!android::base::WideToUTF8(path, &home_str)) {
+ return {};
+ }
+ return home_str;
+#else
+ if (const char* const home = getenv("HOME")) {
+ return home;
+ }
+
+ struct passwd pwent;
+ struct passwd* result;
+ int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (pwent_max == -1) {
+ pwent_max = 16384;
+ }
+ std::vector<char> buf(pwent_max);
+ int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
+ if (rc == 0 && result) {
+ return result->pw_dir;
+ }
+#endif
+
+ return {};
+}
+
+bool FileExists(const std::string& path) {
+ return access(path.c_str(), F_OK) == 0;
+}
+
+bool EnsureDirectoryExists(const std::string& directory_path) {
+ const int result =
+#ifdef _WIN32
+ _mkdir(directory_path.c_str());
+#else
+ mkdir(directory_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#endif
+
+ return result == 0 || errno == EEXIST;
+}
+
+FileLock::FileLock(const std::string& path) : fd_(open(path.c_str(), O_CREAT | O_WRONLY, 0644)) {
+ if (LockFile(fd_.get()) != 0) {
+ LOG(FATAL) << "Failed to acquire a lock on " << path;
+ }
+}
\ No newline at end of file
diff --git a/fastboot/filesystem.h b/fastboot/filesystem.h
new file mode 100644
index 0000000..c5f9c94
--- /dev/null
+++ b/fastboot/filesystem.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 <android-base/unique_fd.h>
+
+#include <string>
+
+using android::base::unique_fd;
+
+// TODO(b/175635923): remove after enabling libc++fs for windows
+const char kPathSeparator =
+#ifdef _WIN32
+ '\\';
+#else
+ '/';
+#endif
+
+std::string GetHomeDirPath();
+bool FileExists(const std::string& path);
+bool EnsureDirectoryExists(const std::string& directory_path);
+
+class FileLock {
+ public:
+ FileLock() = delete;
+ FileLock(const std::string& path);
+
+ private:
+ unique_fd fd_;
+};
\ No newline at end of file
diff --git a/fastboot/fuzzer/Android.bp b/fastboot/fuzzer/Android.bp
index 1b59e4a..a898070 100644
--- a/fastboot/fuzzer/Android.bp
+++ b/fastboot/fuzzer/Android.bp
@@ -58,5 +58,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 533764,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libfastboot library",
+ vector: "local_no_privileges_required",
+ service_privilege: "host_only",
+ users: "single_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/fastboot/mock_transport.h b/fastboot/mock_transport.h
new file mode 100644
index 0000000..cc3840c
--- /dev/null
+++ b/fastboot/mock_transport.h
@@ -0,0 +1,67 @@
+//
+// 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.h>
+
+#include <algorithm>
+#include <string_view>
+
+#include <gmock/gmock.h>
+#include "transport.h"
+
+class MockTransport : public Transport {
+ public:
+ MOCK_METHOD(ssize_t, Read, (void* data, size_t len), (override));
+ MOCK_METHOD(ssize_t, Write, (const void* data, size_t len), (override));
+ MOCK_METHOD(int, Close, (), (override));
+ MOCK_METHOD(int, Reset, (), (override));
+};
+
+class RawDataMatcher {
+ public:
+ explicit RawDataMatcher(const char* data) : data_(data) {}
+ explicit RawDataMatcher(std::string_view data) : data_(data) {}
+
+ bool MatchAndExplain(std::tuple<const void*, size_t> args,
+ ::testing::MatchResultListener*) const {
+ const void* expected_data = std::get<0>(args);
+ size_t expected_len = std::get<1>(args);
+ if (expected_len != data_.size()) {
+ return false;
+ }
+ return memcmp(expected_data, data_.data(), expected_len) == 0;
+ }
+ void DescribeTo(std::ostream* os) const { *os << "raw data is"; }
+ void DescribeNegationTo(std::ostream* os) const { *os << "raw data is not"; }
+
+ private:
+ std::string_view data_;
+};
+
+template <typename T>
+static inline ::testing::PolymorphicMatcher<RawDataMatcher> RawData(T data) {
+ return ::testing::MakePolymorphicMatcher(RawDataMatcher(data));
+}
+
+static inline auto CopyData(const char* source) {
+ return [source](void* buffer, size_t size) -> ssize_t {
+ size_t to_copy = std::min(size, strlen(source));
+ memcpy(buffer, source, to_copy);
+ return to_copy;
+ };
+};
diff --git a/fastboot/result.h b/fastboot/result.h
new file mode 100644
index 0000000..dfa5e10
--- /dev/null
+++ b/fastboot/result.h
@@ -0,0 +1,53 @@
+/*
+ * 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 <android-base/result.h>
+
+#include "util.h"
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::base::ResultError;
+
+class FastbootError {
+ public:
+ enum Type { NETWORK_SERIAL_WRONG_PREFIX = 1, NETWORK_SERIAL_WRONG_ADDRESS = 2 };
+
+ FastbootError(Type&& type) : type_(std::forward<Type>(type)) {}
+
+ Type value() const { return type_; }
+ operator Type() const { return value(); }
+ std::string print() const { return ""; }
+
+ private:
+ Type type_;
+};
+
+template <typename T, typename U>
+inline T Expect(Result<T, U> r) {
+ if (r.ok()) {
+ return r.value();
+ }
+
+ die(r.error().message());
+
+ return r.value();
+}
\ No newline at end of file
diff --git a/fastboot/storage.cpp b/fastboot/storage.cpp
new file mode 100644
index 0000000..629ebc8
--- /dev/null
+++ b/fastboot/storage.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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 <android-base/file.h>
+#include <android-base/logging.h>
+
+#include <fstream>
+#include <iterator>
+
+#include "storage.h"
+#include "util.h"
+
+ConnectedDevicesStorage::ConnectedDevicesStorage() {
+ home_fastboot_path_ = GetHomeDirPath() + kPathSeparator + ".fastboot";
+ devices_path_ = home_fastboot_path_ + kPathSeparator + "devices";
+
+ // We're using a separate file for locking because the Windows LockFileEx does not
+ // permit opening a file stream for the locked file, even within the same process. So,
+ // we have to use fd or handle API to manipulate the storage files, which makes it
+ // nearly impossible to fully rewrite a file content without having to recreate it.
+ // Unfortunately, this is not an option during holding a lock.
+ devices_lock_path_ = home_fastboot_path_ + kPathSeparator + "devices.lock";
+}
+
+bool ConnectedDevicesStorage::Exists() const {
+ return FileExists(devices_path_);
+}
+
+void ConnectedDevicesStorage::WriteDevices(const FileLock&, const std::set<std::string>& devices) {
+ std::ofstream devices_stream(devices_path_);
+ std::copy(devices.begin(), devices.end(),
+ std::ostream_iterator<std::string>(devices_stream, "\n"));
+}
+
+std::set<std::string> ConnectedDevicesStorage::ReadDevices(const FileLock&) {
+ std::ifstream devices_stream(devices_path_);
+ std::istream_iterator<std::string> start(devices_stream), end;
+ std::set<std::string> devices(start, end);
+ return devices;
+}
+
+void ConnectedDevicesStorage::Clear(const FileLock&) {
+ if (!android::base::RemoveFileIfExists(devices_path_)) {
+ LOG(FATAL) << "Failed to clear connected device list: " << devices_path_;
+ }
+}
+
+FileLock ConnectedDevicesStorage::Lock() const {
+ if (!EnsureDirectoryExists(home_fastboot_path_)) {
+ LOG(FATAL) << "Cannot create directory: " << home_fastboot_path_;
+ }
+ return FileLock(devices_lock_path_);
+}
diff --git a/fastboot/storage.h b/fastboot/storage.h
new file mode 100644
index 0000000..ae9d846
--- /dev/null
+++ b/fastboot/storage.h
@@ -0,0 +1,38 @@
+/*
+ * 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 <set>
+#include <string>
+
+#include "filesystem.h"
+
+class ConnectedDevicesStorage {
+ public:
+ ConnectedDevicesStorage();
+
+ bool Exists() const;
+ void WriteDevices(const FileLock&, const std::set<std::string>& devices);
+ std::set<std::string> ReadDevices(const FileLock&);
+ void Clear(const FileLock&);
+ FileLock Lock() const;
+
+ private:
+ std::string home_fastboot_path_;
+ std::string devices_path_;
+ std::string devices_lock_path_;
+};
\ No newline at end of file
diff --git a/fastboot/super_flash_helper.cpp b/fastboot/super_flash_helper.cpp
new file mode 100644
index 0000000..b617ce8
--- /dev/null
+++ b/fastboot/super_flash_helper.cpp
@@ -0,0 +1,125 @@
+//
+// 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 "super_flash_helper.h"
+
+#include <android-base/logging.h>
+
+#include "util.h"
+
+using android::base::borrowed_fd;
+using android::base::unique_fd;
+using android::fs_mgr::SuperImageExtent;
+
+SuperFlashHelper::SuperFlashHelper(const ImageSource& source) : source_(source) {}
+
+bool SuperFlashHelper::Open(borrowed_fd fd) {
+ if (!builder_.Open(fd)) {
+ LOG(VERBOSE) << "device does not support optimized super flashing";
+ return false;
+ }
+
+ base_metadata_ = builder_.Export();
+ return !!base_metadata_;
+}
+
+bool SuperFlashHelper::IncludeInSuper(const std::string& partition) {
+ return should_flash_in_userspace(*base_metadata_.get(), partition);
+}
+
+bool SuperFlashHelper::AddPartition(const std::string& partition, const std::string& image_name,
+ bool optional) {
+ if (!IncludeInSuper(partition)) {
+ return true;
+ }
+ auto iter = image_fds_.find(image_name);
+ if (iter == image_fds_.end()) {
+ unique_fd fd = source_.OpenFile(image_name);
+ if (fd < 0) {
+ if (!optional) {
+ LOG(VERBOSE) << "could not find partition image: " << image_name;
+ return false;
+ }
+ return true;
+ }
+ if (is_sparse_file(fd)) {
+ LOG(VERBOSE) << "cannot optimize dynamic partitions with sparse images";
+ return false;
+ }
+ iter = image_fds_.emplace(image_name, std::move(fd)).first;
+ }
+
+ if (!builder_.AddPartition(partition, image_name, get_file_size(iter->second))) {
+ return false;
+ }
+
+ will_flash_.emplace(partition);
+ return true;
+}
+
+SparsePtr SuperFlashHelper::GetSparseLayout() {
+ // Cache extents since the sparse ptr depends on data pointers.
+ if (extents_.empty()) {
+ extents_ = builder_.GetImageLayout();
+ if (extents_.empty()) {
+ LOG(VERBOSE) << "device does not support optimized super flashing";
+ return {nullptr, nullptr};
+ }
+ }
+
+ unsigned int block_size = base_metadata_->geometry.logical_block_size;
+ int64_t flashed_size = extents_.back().offset + extents_.back().size;
+ SparsePtr s(sparse_file_new(block_size, flashed_size), sparse_file_destroy);
+
+ for (const auto& extent : extents_) {
+ if (extent.offset / block_size > UINT_MAX) {
+ // Super image is too big to send via sparse files (>8TB).
+ LOG(VERBOSE) << "super image is too big to flash";
+ return {nullptr, nullptr};
+ }
+ unsigned int block = extent.offset / block_size;
+
+ int rv = 0;
+ switch (extent.type) {
+ case SuperImageExtent::Type::DONTCARE:
+ break;
+ case SuperImageExtent::Type::ZERO:
+ rv = sparse_file_add_fill(s.get(), 0, extent.size, block);
+ break;
+ case SuperImageExtent::Type::DATA:
+ rv = sparse_file_add_data(s.get(), extent.blob->data(), extent.size, block);
+ break;
+ case SuperImageExtent::Type::PARTITION: {
+ auto iter = image_fds_.find(extent.image_name);
+ if (iter == image_fds_.end()) {
+ LOG(FATAL) << "image added but not found: " << extent.image_name;
+ return {nullptr, nullptr};
+ }
+ rv = sparse_file_add_fd(s.get(), iter->second.get(), extent.image_offset,
+ extent.size, block);
+ break;
+ }
+ default:
+ LOG(VERBOSE) << "unrecognized extent type in super image layout";
+ return {nullptr, nullptr};
+ }
+ if (rv) {
+ LOG(VERBOSE) << "sparse failure building super image layout";
+ return {nullptr, nullptr};
+ }
+ }
+ return s;
+}
diff --git a/fastboot/super_flash_helper.h b/fastboot/super_flash_helper.h
new file mode 100644
index 0000000..29c15d0
--- /dev/null
+++ b/fastboot/super_flash_helper.h
@@ -0,0 +1,56 @@
+//
+// 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 <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <android-base/unique_fd.h>
+#include <liblp/liblp.h>
+#include <liblp/super_layout_builder.h>
+
+#include "util.h"
+
+class SuperFlashHelper final {
+ public:
+ explicit SuperFlashHelper(const ImageSource& source);
+
+ bool Open(android::base::borrowed_fd fd);
+ bool IncludeInSuper(const std::string& partition);
+ bool AddPartition(const std::string& partition, const std::string& image_name, bool optional);
+
+ // Note: the SparsePtr if non-null should not outlive SuperFlashHelper, since
+ // it depends on open fds and data pointers.
+ SparsePtr GetSparseLayout();
+
+ bool WillFlash(const std::string& partition) const {
+ return will_flash_.find(partition) != will_flash_.end();
+ }
+
+ private:
+ const ImageSource& source_;
+ android::fs_mgr::SuperLayoutBuilder builder_;
+ std::unique_ptr<android::fs_mgr::LpMetadata> base_metadata_;
+ std::vector<android::fs_mgr::SuperImageExtent> extents_;
+
+ // Cache open image fds. This keeps them alive while we flash the sparse
+ // file.
+ std::unordered_map<std::string, android::base::unique_fd> image_fds_;
+ std::unordered_set<std::string> will_flash_;
+};
diff --git a/fastboot/super_flash_helper_test.cpp b/fastboot/super_flash_helper_test.cpp
new file mode 100644
index 0000000..82b8aa5
--- /dev/null
+++ b/fastboot/super_flash_helper_test.cpp
@@ -0,0 +1,88 @@
+//
+// 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 "super_flash_helper.h"
+
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+#include <sparse/sparse.h>
+
+using android::base::unique_fd;
+
+unique_fd OpenTestFile(const std::string& file, int flags) {
+ std::string path = "testdata/" + file;
+
+ unique_fd fd(open(path.c_str(), flags));
+ if (fd >= 0) {
+ return fd;
+ }
+
+ path = android::base::GetExecutableDirectory() + "/" + path;
+ return unique_fd{open(path.c_str(), flags)};
+}
+
+class TestImageSource final : public ImageSource {
+ public:
+ bool ReadFile(const std::string&, std::vector<char>*) const override {
+ // Not used here.
+ return false;
+ }
+ unique_fd OpenFile(const std::string& name) const override {
+ return OpenTestFile(name, O_RDONLY | O_CLOEXEC);
+ }
+};
+
+TEST(SuperFlashHelper, ImageEquality) {
+ auto super_empty_fd = OpenTestFile("super_empty.img", O_RDONLY);
+ ASSERT_GE(super_empty_fd, 0);
+
+ TestImageSource source;
+ SuperFlashHelper helper(source);
+ ASSERT_TRUE(helper.Open(super_empty_fd));
+ ASSERT_TRUE(helper.AddPartition("system_a", "system.img", false));
+
+ auto sparse_file = helper.GetSparseLayout();
+ ASSERT_NE(sparse_file, nullptr);
+
+ TemporaryFile fb_super;
+ ASSERT_GE(fb_super.fd, 0);
+ ASSERT_EQ(sparse_file_write(sparse_file.get(), fb_super.fd, false, false, false), 0);
+
+ auto real_super_fd = OpenTestFile("super.img", O_RDONLY);
+ ASSERT_GE(real_super_fd, 0);
+
+ std::string expected(get_file_size(real_super_fd), '\0');
+ ASSERT_FALSE(expected.empty());
+ ASSERT_TRUE(android::base::ReadFully(real_super_fd, expected.data(), expected.size()));
+
+ std::string actual(get_file_size(fb_super.fd), '\0');
+ ASSERT_FALSE(actual.empty());
+ ASSERT_EQ(lseek(fb_super.fd, 0, SEEK_SET), 0);
+ ASSERT_TRUE(android::base::ReadFully(fb_super.fd, actual.data(), actual.size()));
+
+ // The helper doesn't add any extra zeroes to the image, whereas lpmake does, to
+ // pad to the entire super size.
+ ASSERT_LE(actual.size(), expected.size());
+ for (size_t i = 0; i < actual.size(); i++) {
+ ASSERT_EQ(actual[i], expected[i]) << "byte mismatch at position " << i;
+ }
+ for (size_t i = actual.size(); i < expected.size(); i++) {
+ ASSERT_EQ(expected[i], 0) << "byte mismatch at position " << i;
+ }
+}
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
new file mode 100644
index 0000000..c1b9a31
--- /dev/null
+++ b/fastboot/task.cpp
@@ -0,0 +1,340 @@
+//
+// 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 "task.h"
+
+#include <iostream>
+
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+
+#include "fastboot.h"
+#include "filesystem.h"
+#include "super_flash_helper.h"
+#include "util.h"
+
+using namespace std::string_literals;
+FlashTask::FlashTask(const std::string& slot, const std::string& pname, const std::string& fname,
+ const bool apply_vbmeta, const FlashingPlan* fp)
+ : pname_(pname), fname_(fname), slot_(slot), apply_vbmeta_(apply_vbmeta), fp_(fp) {}
+
+void FlashTask::Run() {
+ auto flash = [&](const std::string& partition) {
+ if (should_flash_in_userspace(partition) && !is_userspace_fastboot()) {
+ die("The partition you are trying to flash is dynamic, and "
+ "should be flashed via fastbootd. Please run:\n"
+ "\n"
+ " fastboot reboot fastboot\n"
+ "\n"
+ "And try again. If you are intentionally trying to "
+ "overwrite a fixed partition, use --force.");
+ }
+ do_flash(partition.c_str(), fname_.c_str(), apply_vbmeta_, fp_);
+ };
+ do_for_partitions(pname_, slot_, flash, true);
+}
+
+std::string FlashTask::ToString() {
+ std::string apply_vbmeta_string = "";
+ if (apply_vbmeta_) {
+ apply_vbmeta_string = " --apply_vbmeta";
+ }
+ return "flash" + apply_vbmeta_string + " " + pname_ + " " + fname_;
+}
+
+std::string FlashTask::GetPartitionAndSlot() {
+ auto slot = slot_;
+ if (slot.empty()) {
+ slot = get_current_slot();
+ }
+ if (slot.empty()) {
+ return pname_;
+ }
+ if (slot == "all") {
+ LOG(FATAL) << "Cannot retrieve a singular name when using all slots";
+ }
+ return pname_ + "_" + slot;
+}
+
+RebootTask::RebootTask(const FlashingPlan* fp) : fp_(fp){};
+RebootTask::RebootTask(const FlashingPlan* fp, const std::string& reboot_target)
+ : reboot_target_(reboot_target), fp_(fp){};
+
+void RebootTask::Run() {
+ if (reboot_target_ == "fastboot") {
+ if (!is_userspace_fastboot()) {
+ reboot_to_userspace_fastboot();
+ fp_->fb->WaitForDisconnect();
+ }
+ } else if (reboot_target_ == "recovery") {
+ fp_->fb->RebootTo("recovery");
+ fp_->fb->WaitForDisconnect();
+ } else if (reboot_target_ == "bootloader") {
+ fp_->fb->RebootTo("bootloader");
+ fp_->fb->WaitForDisconnect();
+ } else if (reboot_target_ == "") {
+ fp_->fb->Reboot();
+ fp_->fb->WaitForDisconnect();
+ } else {
+ syntax_error("unknown reboot target %s", reboot_target_.c_str());
+ }
+}
+
+std::string RebootTask::ToString() {
+ 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)
+ : super_name_(super_name),
+ helper_(std::move(helper)),
+ sparse_layout_(std::move(sparse_layout)),
+ super_size_(super_size),
+ fp_(fp) {}
+
+void FlashSuperLayoutTask::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.
+ std::vector<SparsePtr> files;
+ if (int limit = get_sparse_limit(super_size_, fp_)) {
+ files = resparse_file(sparse_layout_.get(), limit);
+ } else {
+ files.emplace_back(std::move(sparse_layout_));
+ }
+
+ // Send the data to the device.
+ flash_partition_files(super_name_, files);
+}
+std::string FlashSuperLayoutTask::ToString() {
+ return "optimized-flash-super";
+}
+
+std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize(
+ const FlashingPlan* fp, std::vector<ImageEntry>& os_images) {
+ if (!fp->should_optimize_flash_super) {
+ LOG(INFO) << "super optimization is disabled";
+ return nullptr;
+ }
+ if (!supports_AB()) {
+ LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
+ return nullptr;
+ }
+ if (fp->slot_override == "all") {
+ LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
+ return nullptr;
+ }
+
+ // Does this device use dynamic partitions at all?
+ unique_fd fd = fp->source->OpenFile("super_empty.img");
+
+ if (fd < 0) {
+ LOG(VERBOSE) << "could not open super_empty.img";
+ return nullptr;
+ }
+
+ std::string super_name;
+ // Try to find whether there is a super partition.
+ if (fp->fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) {
+ super_name = "super";
+ }
+
+ uint64_t partition_size;
+ std::string partition_size_str;
+ if (fp->fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) {
+ LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition";
+ return nullptr;
+ }
+ partition_size_str = fb_fix_numeric_var(partition_size_str);
+ if (!android::base::ParseUint(partition_size_str, &partition_size)) {
+ LOG(VERBOSE) << "Could not parse " << super_name << " size: " << partition_size_str;
+ return nullptr;
+ }
+
+ std::unique_ptr<SuperFlashHelper> helper = std::make_unique<SuperFlashHelper>(*fp->source);
+ if (!helper->Open(fd)) {
+ return nullptr;
+ }
+
+ for (const auto& entry : os_images) {
+ auto partition = GetPartitionName(entry, fp->current_slot);
+ auto image = entry.first;
+
+ if (!helper->AddPartition(partition, image->img_name, image->optional_if_no_image)) {
+ return nullptr;
+ }
+ }
+
+ auto s = helper->GetSparseLayout();
+ if (!s) return nullptr;
+
+ // Remove images that we already flashed, just in case we have non-dynamic OS images.
+ auto remove_if_callback = [&](const ImageEntry& entry) -> bool {
+ return helper->WillFlash(GetPartitionName(entry, fp->current_slot));
+ };
+ 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);
+}
+
+std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::InitializeFromTasks(
+ const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks) {
+ if (!fp->should_optimize_flash_super) {
+ LOG(INFO) << "super optimization is disabled";
+ return nullptr;
+ }
+ if (!supports_AB()) {
+ LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
+ return nullptr;
+ }
+ if (fp->slot_override == "all") {
+ LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
+ return nullptr;
+ }
+
+ // Does this device use dynamic partitions at all?
+ unique_fd fd = fp->source->OpenFile("super_empty.img");
+
+ if (fd < 0) {
+ LOG(VERBOSE) << "could not open super_empty.img";
+ return nullptr;
+ }
+
+ std::string super_name;
+ // Try to find whether there is a super partition.
+ if (fp->fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) {
+ super_name = "super";
+ }
+ uint64_t partition_size;
+ std::string partition_size_str;
+ if (fp->fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) {
+ LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition";
+ return nullptr;
+ }
+ partition_size_str = fb_fix_numeric_var(partition_size_str);
+ if (!android::base::ParseUint(partition_size_str, &partition_size)) {
+ LOG(VERBOSE) << "Could not parse " << super_name << " size: " << partition_size_str;
+ return nullptr;
+ }
+
+ std::unique_ptr<SuperFlashHelper> helper = std::make_unique<SuperFlashHelper>(*fp->source);
+ if (!helper->Open(fd)) {
+ return nullptr;
+ }
+
+ for (const auto& task : tasks) {
+ if (auto flash_task = task->AsFlashTask()) {
+ auto partition = flash_task->GetPartitionAndSlot();
+ if (!helper->AddPartition(partition, flash_task->GetImageName(), false)) {
+ return nullptr;
+ }
+ }
+ }
+
+ auto s = helper->GetSparseLayout();
+ if (!s) return nullptr;
+ // Remove images that we already flashed, just in case we have non-dynamic OS images.
+ auto remove_if_callback = [&](const auto& task) -> bool {
+ if (auto flash_task = task->AsFlashTask()) {
+ return helper->WillFlash(flash_task->GetPartitionAndSlot());
+ } else if (auto update_super_task = task->AsUpdateSuperTask()) {
+ return true;
+ } else if (auto reboot_task = task->AsRebootTask()) {
+ return true;
+ }
+ return false;
+ };
+ 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);
+}
+
+UpdateSuperTask::UpdateSuperTask(const FlashingPlan* fp) : fp_(fp) {}
+
+void UpdateSuperTask::Run() {
+ unique_fd fd = fp_->source->OpenFile("super_empty.img");
+ if (fd < 0) {
+ return;
+ }
+ if (!is_userspace_fastboot()) {
+ reboot_to_userspace_fastboot();
+ }
+
+ std::string super_name;
+ if (fp_->fb->GetVar("super-partition-name", &super_name) != fastboot::RetCode::SUCCESS) {
+ super_name = "super";
+ }
+ fp_->fb->Download(super_name, fd, get_file_size(fd));
+
+ std::string command = "update-super:" + super_name;
+ if (fp_->wants_wipe) {
+ command += ":wipe";
+ }
+ fp_->fb->RawCommand(command, "Updating super partition");
+}
+std::string UpdateSuperTask::ToString() {
+ return "update-super";
+}
+
+ResizeTask::ResizeTask(const FlashingPlan* fp, const std::string& pname, const std::string& size,
+ const std::string& slot)
+ : fp_(fp), pname_(pname), size_(size), slot_(slot) {}
+
+void ResizeTask::Run() {
+ auto resize_partition = [this](const std::string& partition) -> void {
+ if (is_logical(partition)) {
+ fp_->fb->ResizePartition(partition, size_);
+ }
+ };
+ do_for_partitions(pname_, slot_, resize_partition, false);
+}
+
+std::string ResizeTask::ToString() {
+ return "resize " + pname_;
+}
+
+DeleteTask::DeleteTask(const FlashingPlan* fp, const std::string& pname) : fp_(fp), pname_(pname){};
+
+void DeleteTask::Run() {
+ fp_->fb->DeletePartition(pname_);
+}
+
+std::string DeleteTask::ToString() {
+ return "delete " + pname_;
+}
+
+WipeTask::WipeTask(const FlashingPlan* fp, const std::string& pname) : fp_(fp), pname_(pname){};
+
+void WipeTask::Run() {
+ std::string partition_type;
+ if (fp_->fb->GetVar("partition-type:" + pname_, &partition_type) != fastboot::SUCCESS) {
+ LOG(ERROR) << "wipe task partition not found: " << pname_;
+ return;
+ }
+ if (partition_type.empty()) return;
+ if (fp_->fb->Erase(pname_) != fastboot::SUCCESS) {
+ LOG(ERROR) << "wipe task erase failed with partition: " << pname_;
+ return;
+ }
+ fb_perform_format(pname_, 1, partition_type, "", fp_->fs_options, fp_);
+}
+
+std::string WipeTask::ToString() {
+ return "erase " + pname_;
+}
diff --git a/fastboot/task.h b/fastboot/task.h
new file mode 100644
index 0000000..858f43a
--- /dev/null
+++ b/fastboot/task.h
@@ -0,0 +1,149 @@
+//
+// Copyright (C) 2020 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 <sstream>
+#include <string>
+
+#include "fastboot_driver.h"
+#include "super_flash_helper.h"
+#include "util.h"
+
+struct FlashingPlan;
+struct Image;
+using ImageEntry = std::pair<const Image*, std::string>;
+
+class FlashTask;
+class RebootTask;
+class UpdateSuperTask;
+class WipeTask;
+
+class Task {
+ public:
+ Task() = default;
+ virtual void Run() = 0;
+ virtual std::string ToString() = 0;
+
+ virtual FlashTask* AsFlashTask() { return nullptr; }
+ virtual RebootTask* AsRebootTask() { return nullptr; }
+ virtual UpdateSuperTask* AsUpdateSuperTask() { return nullptr; }
+ virtual WipeTask* AsWipeTask() { return nullptr; }
+
+ virtual ~Task() = default;
+};
+
+class FlashTask : public Task {
+ public:
+ FlashTask(const std::string& slot, const std::string& pname, const std::string& fname,
+ const bool apply_vbmeta, const FlashingPlan* fp);
+ virtual FlashTask* AsFlashTask() override { return this; }
+
+ void Run() override;
+ std::string ToString() override;
+ std::string GetPartition() { return pname_; }
+ std::string GetImageName() { return fname_; }
+ std::string GetSlot() { return slot_; }
+ std::string GetPartitionAndSlot();
+
+ private:
+ const std::string pname_;
+ const std::string fname_;
+ const std::string slot_;
+ const bool apply_vbmeta_;
+ const FlashingPlan* fp_;
+};
+
+class RebootTask : public Task {
+ public:
+ RebootTask(const FlashingPlan* fp);
+ RebootTask(const FlashingPlan* fp, const std::string& reboot_target);
+ virtual RebootTask* AsRebootTask() override { return this; }
+ void Run() override;
+ std::string ToString() override;
+
+ private:
+ const std::string reboot_target_ = "";
+ const FlashingPlan* fp_;
+};
+
+class FlashSuperLayoutTask : 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(
+ const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks);
+ using ImageEntry = std::pair<const Image*, std::string>;
+ void Run() override;
+ std::string ToString() override;
+
+ private:
+ const std::string super_name_;
+ std::unique_ptr<SuperFlashHelper> helper_;
+ SparsePtr sparse_layout_;
+ uint64_t super_size_;
+ const FlashingPlan* fp_;
+};
+
+class UpdateSuperTask : public Task {
+ public:
+ UpdateSuperTask(const FlashingPlan* fp);
+ virtual UpdateSuperTask* AsUpdateSuperTask() override { return this; }
+
+ void Run() override;
+ std::string ToString() override;
+
+ private:
+ const FlashingPlan* fp_;
+};
+
+class ResizeTask : public Task {
+ public:
+ ResizeTask(const FlashingPlan* fp, const std::string& pname, const std::string& size,
+ const std::string& slot);
+ void Run() override;
+ std::string ToString() override;
+
+ private:
+ const FlashingPlan* fp_;
+ const std::string pname_;
+ const std::string size_;
+ const std::string slot_;
+};
+
+class DeleteTask : public Task {
+ public:
+ DeleteTask(const FlashingPlan* fp, const std::string& pname);
+ void Run() override;
+ std::string ToString() override;
+
+ private:
+ const FlashingPlan* fp_;
+ const std::string pname_;
+};
+
+class WipeTask : public Task {
+ public:
+ WipeTask(const FlashingPlan* fp, const std::string& pname);
+ virtual WipeTask* AsWipeTask() override { return this; }
+ void Run() override;
+ std::string ToString() override;
+
+ private:
+ const FlashingPlan* fp_;
+ const std::string pname_;
+};
diff --git a/fastboot/task_test.cpp b/fastboot/task_test.cpp
new file mode 100644
index 0000000..b4e139b
--- /dev/null
+++ b/fastboot/task_test.cpp
@@ -0,0 +1,161 @@
+//
+// 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 "task.h"
+#include "fastboot.h"
+#include "fastboot_driver_mock.h"
+
+#include <gtest/gtest.h>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <unordered_map>
+#include "android-base/strings.h"
+using android::base::Split;
+using testing::_;
+
+class ParseTest : public ::testing ::Test {
+ protected:
+ void SetUp() override {
+ fp = std::make_unique<FlashingPlan>();
+ fp->slot_override = "b";
+ fp->secondary_slot = "a";
+ fp->wants_wipe = false;
+ }
+ void TearDown() override {}
+
+ std::unique_ptr<FlashingPlan> fp;
+
+ private:
+};
+
+static std::vector<std::unique_ptr<Task>> collectTasks(FlashingPlan* fp,
+ const std::vector<std::string>& commands) {
+ std::vector<std::vector<std::string>> vec_commands;
+ for (auto& command : commands) {
+ vec_commands.emplace_back(android::base::Split(command, " "));
+ }
+ std::vector<std::unique_ptr<Task>> tasks;
+ for (auto& command : vec_commands) {
+ tasks.emplace_back(ParseFastbootInfoLine(fp, command));
+ }
+ return tasks;
+}
+
+std::unique_ptr<Task> ParseCommand(FlashingPlan* fp, std::string command) {
+ std::vector<std::string> vec_command = android::base::Split(command, " ");
+ return ParseFastbootInfoLine(fp, vec_command);
+}
+
+TEST_F(ParseTest, CorrectFlashTaskFormed) {
+ std::vector<std::string> commands = {"flash dtbo", "flash --slot-other system system_other.img",
+ "flash system", "flash --apply-vbmeta vbmeta"};
+
+ std::vector<std::unique_ptr<Task>> tasks = collectTasks(fp.get(), commands);
+
+ std::vector<std::vector<std::string>> expected_values{
+ {"dtbo", "dtbo_b", "b", "dtbo.img"},
+ {"system", "system_a", "a", "system_other.img"},
+ {"system", "system_b", "b", "system.img"},
+ {"vbmeta", "vbmeta_b", "b", "vbmeta.img"}
+
+ };
+
+ for (auto& task : tasks) {
+ ASSERT_TRUE(task != nullptr);
+ }
+
+ for (size_t i = 0; i < tasks.size(); i++) {
+ auto task = tasks[i]->AsFlashTask();
+ ASSERT_TRUE(task != nullptr);
+ ASSERT_EQ(task->GetPartition(), expected_values[i][0]);
+ ASSERT_EQ(task->GetPartitionAndSlot(), expected_values[i][1]);
+ ASSERT_EQ(task->GetSlot(), expected_values[i][2]);
+ ASSERT_EQ(task->GetImageName(), expected_values[i][3]);
+ }
+}
+
+TEST_F(ParseTest, VersionCheckCorrect) {
+ std::vector<std::string> correct_versions = {"version 1", "version 22", "version 5",
+ "version 17"};
+
+ std::vector<std::string> bad_versions = {"version", "version .01", "version x1",
+ "version 1.0.1", "version 1.", "s 1.0",
+ "version 1.0 2.0", "version 100.00", "version 1 2"};
+
+ for (auto& version : correct_versions) {
+ ASSERT_TRUE(CheckFastbootInfoRequirements(android::base::Split(version, " "), 26))
+ << version;
+ }
+
+ // returning False for failing version check
+ for (auto& version : correct_versions) {
+ ASSERT_FALSE(CheckFastbootInfoRequirements(android::base::Split(version, " "), 0))
+ << version;
+ }
+ // returning False for bad format
+ for (auto& version : bad_versions) {
+ ASSERT_FALSE(CheckFastbootInfoRequirements(android::base::Split(version, " "), 100))
+ << version;
+ }
+}
+
+TEST_F(ParseTest, BadFastbootInput) {
+ ASSERT_EQ(ParseCommand(fp.get(), "flash"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "flash --slot-other --apply-vbmeta"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "flash --apply-vbmeta"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "if-wipe"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "if-wipe flash"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "wipe dtbo"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "update-super dtbo"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "flash system system.img system"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "reboot bootloader fastboot"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(),
+ "flash --slot-other --apply-vbmeta system system_other.img system"),
+ nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "erase"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "erase dtbo dtbo"), nullptr);
+ ASSERT_EQ(ParseCommand(fp.get(), "wipe this"), nullptr);
+}
+
+TEST_F(ParseTest, CorrectTaskFormed) {
+ std::vector<std::string> commands = {"flash dtbo", "flash --slot-other system system_other.img",
+ "reboot bootloader", "update-super", "erase cache"};
+ std::vector<std::unique_ptr<Task>> tasks = collectTasks(fp.get(), commands);
+
+ ASSERT_TRUE(tasks[0]->AsFlashTask());
+ ASSERT_TRUE(tasks[0]->AsFlashTask());
+ ASSERT_TRUE(tasks[1]->AsFlashTask());
+ ASSERT_TRUE(tasks[2]->AsRebootTask());
+ ASSERT_TRUE(tasks[3]->AsUpdateSuperTask());
+ ASSERT_TRUE(tasks[4]->AsWipeTask());
+}
+
+TEST_F(ParseTest, CorrectDriverCalls) {
+ fastboot::MockFastbootDriver fb;
+ fp->fb = &fb;
+
+ EXPECT_CALL(fb, RebootTo(_, _, _)).Times(1);
+ EXPECT_CALL(fb, Reboot(_, _)).Times(1);
+ EXPECT_CALL(fb, WaitForDisconnect()).Times(2);
+
+ std::vector<std::string> commands = {"reboot bootloader", "reboot"};
+ std::vector<std::unique_ptr<Task>> tasks = collectTasks(fp.get(), commands);
+
+ for (auto& task : tasks) {
+ task->Run();
+ }
+}
diff --git a/fastboot/testdata/make_super_images.sh b/fastboot/testdata/make_super_images.sh
new file mode 100644
index 0000000..71c54ee
--- /dev/null
+++ b/fastboot/testdata/make_super_images.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+set -e
+set -x
+
+lpmake \
+ --device-size=auto \
+ --metadata-size=4096 \
+ --metadata-slots=3 \
+ --partition=system_a:readonly:0 \
+ --alignment=16384 \
+ --output=super_empty.img
+
+lpmake \
+ --device-size=auto \
+ --metadata-size=4096 \
+ --metadata-slots=3 \
+ --partition=system_a:readonly:0 \
+ --alignment=16384 \
+ --output=super.img \
+ --image=system_a=system.img
diff --git a/fastboot/testdata/super.img b/fastboot/testdata/super.img
new file mode 100644
index 0000000..be13d36
--- /dev/null
+++ b/fastboot/testdata/super.img
Binary files differ
diff --git a/fastboot/testdata/super_empty.img b/fastboot/testdata/super_empty.img
new file mode 100644
index 0000000..4b25869
--- /dev/null
+++ b/fastboot/testdata/super_empty.img
Binary files differ
diff --git a/fastboot/testdata/system.img b/fastboot/testdata/system.img
new file mode 100644
index 0000000..b360610
--- /dev/null
+++ b/fastboot/testdata/system.img
Binary files differ
diff --git a/fastboot/usb.h b/fastboot/usb.h
index e5f56e2..69581ab 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -28,6 +28,8 @@
#pragma once
+#include <functional>
+
#include "transport.h"
struct usb_ifc_info {
@@ -61,7 +63,7 @@
virtual int Reset() = 0;
};
-typedef int (*ifc_match_func)(usb_ifc_info *ifc);
+typedef std::function<int(usb_ifc_info*)> ifc_match_func;
// 0 is non blocking
UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms = 0);
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 610eebf..8b852f5 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -191,16 +191,30 @@
// Iterate over the endpoints for this interface and see if there
// are any that do bulk in/out.
- for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; endpoint++) {
+ for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; ++endpoint) {
UInt8 transferType;
- UInt16 maxPacketSize;
+ UInt16 endPointMaxPacketSize = 0;
UInt8 interval;
+
+ // Attempt to retrieve the 'true' packet-size from supported interface.
+ kr = (*interface)
+ ->GetEndpointProperties(interface, 0, endpoint,
+ kUSBOut,
+ &transferType,
+ &endPointMaxPacketSize, &interval);
+ if (kr == kIOReturnSuccess && !endPointMaxPacketSize) {
+ ERR("GetEndpointProperties() returned zero len packet-size");
+ }
+
+ UInt16 pipePropMaxPacketSize;
UInt8 number;
UInt8 direction;
+ // Proceed with extracting the transfer direction, so we can fill in the
+ // appropriate fields (bulkIn or bulkOut).
kr = (*interface)->GetPipeProperties(interface, endpoint,
&direction,
- &number, &transferType, &maxPacketSize, &interval);
+ &number, &transferType, &pipePropMaxPacketSize, &interval);
if (kr == 0) {
if (transferType != kUSBBulk) {
@@ -216,7 +230,8 @@
}
if (handle->info.ifc_protocol == 0x01) {
- handle->zero_mask = maxPacketSize - 1;
+ handle->zero_mask = (endPointMaxPacketSize == 0) ?
+ pipePropMaxPacketSize - 1 : endPointMaxPacketSize - 1;
}
} else {
ERR("could not get pipe properties for endpoint %u (%08x)\n", endpoint, kr);
@@ -421,12 +436,7 @@
for (;;) {
if (! IOIteratorIsValid(iterator)) {
- /*
- * Apple documentation advises resetting the iterator if
- * it should become invalid during iteration.
- */
- IOIteratorReset(iterator);
- continue;
+ break;
}
io_service_t device = IOIteratorNext(iterator);
@@ -441,8 +451,7 @@
}
if (h.success) {
- handle->reset(new usb_handle);
- memcpy(handle->get(), &h, sizeof(usb_handle));
+ handle->reset(new usb_handle(h));
ret = 0;
break;
}
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index 900d6ea..e03012a 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -30,11 +30,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
+#include <sys/stat.h>
#include <sys/time.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+
#include "util.h"
+using android::base::borrowed_fd;
+
static bool g_verbose = false;
double now() {
@@ -73,3 +78,43 @@
}
fprintf(stderr, "\n");
}
+
+bool should_flash_in_userspace(const android::fs_mgr::LpMetadata& metadata,
+ const std::string& partition_name) {
+ for (const auto& partition : metadata.partitions) {
+ auto candidate = android::fs_mgr::GetPartitionName(partition);
+ if (partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED) {
+ // On retrofit devices, we don't know if, or whether, the A or B
+ // slot has been flashed for dynamic partitions. Instead we add
+ // both names to the list as a conservative guess.
+ if (candidate + "_a" == partition_name || candidate + "_b" == partition_name) {
+ return true;
+ }
+ } else if (candidate == partition_name) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool is_sparse_file(borrowed_fd fd) {
+ SparsePtr s(sparse_file_import(fd.get(), false, false), sparse_file_destroy);
+ return !!s;
+}
+
+int64_t get_file_size(borrowed_fd fd) {
+ struct stat sb;
+ if (fstat(fd.get(), &sb) == -1) {
+ die("could not get file size");
+ }
+ return sb.st_size;
+}
+
+std::string fb_fix_numeric_var(std::string var) {
+ // Some bootloaders (angler, for example), send spurious leading whitespace.
+ var = android::base::Trim(var);
+ // Some bootloaders (hammerhead, for example) use implicit hex.
+ // This code used to use strtol with base 16.
+ if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
+ return var;
+}
diff --git a/fastboot/util.h b/fastboot/util.h
index c719df2..fdbc1d6 100644
--- a/fastboot/util.h
+++ b/fastboot/util.h
@@ -4,8 +4,14 @@
#include <stdlib.h>
#include <string>
+#include <vector>
+#include <android-base/unique_fd.h>
#include <bootimg.h>
+#include <liblp/liblp.h>
+#include <sparse/sparse.h>
+
+using SparsePtr = std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)>;
/* util stuff */
double now();
@@ -19,3 +25,16 @@
void verbose(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
void die(const std::string& str) __attribute__((__noreturn__));
+
+bool should_flash_in_userspace(const android::fs_mgr::LpMetadata& metadata,
+ const std::string& partition_name);
+bool is_sparse_file(android::base::borrowed_fd fd);
+int64_t get_file_size(android::base::borrowed_fd fd);
+std::string fb_fix_numeric_var(std::string var);
+
+class ImageSource {
+ public:
+ virtual ~ImageSource(){};
+ virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0;
+ virtual android::base::unique_fd OpenFile(const std::string& name) const = 0;
+};
diff --git a/fastboot/vendor_boot_img_utils_test.cpp b/fastboot/vendor_boot_img_utils_test.cpp
index 1563b89..467c6e9 100644
--- a/fastboot/vendor_boot_img_utils_test.cpp
+++ b/fastboot/vendor_boot_img_utils_test.cpp
@@ -73,8 +73,8 @@
// Seek to beginning then read the whole file.
Result<std::string> ReadStartOfFdToString(borrowed_fd fd, std::filesystem::path path) {
- if (lseek64(fd.get(), 0, SEEK_SET) != 0)
- return ErrnoError() << "lseek64(" << path << ", 0, SEEK_SET)";
+ if (lseek(fd.get(), 0, SEEK_SET) != 0)
+ return ErrnoError() << "lseek(" << path << ", 0, SEEK_SET)";
std::string content;
if (!android::base::ReadFdToString(fd, &content)) return ErrnoError() << "read(" << path << ")";
return content;
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index dd61272..bbd068b 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -181,6 +181,10 @@
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"],
srcs: [
@@ -206,6 +210,7 @@
"libbase_headers",
"libgsi_headers",
],
+ min_sdk_version: "31",
}
cc_binary {
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 432aa4f..d357e45 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -22,10 +22,28 @@
"name": "vts_libsnapshot_test"
},
{
- "name": "libsnapshot_fuzzer_test"
+ "name": "vab_legacy_tests"
},
+ // TODO: b/279009697
+ //{"name": "vabc_legacy_tests"},
{
"name": "cow_api_test"
}
+ ],
+ "kernel-presubmit": [
+ {
+ "name": "vts_libdm_test"
+ },
+ {
+ "name": "vts_core_liblp_test"
+ },
+ {
+ "name": "vts_libsnapshot_test"
+ },
+ {
+ "name": "vab_legacy_tests"
+ }
+ // TODO: b/279009697
+ //{"name": "vabc_legacy_tests"}
]
}
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 1c1ab48..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;
}
@@ -1096,8 +1097,11 @@
class CheckpointManager {
public:
- CheckpointManager(int needs_checkpoint = -1, bool metadata_encrypted = false)
- : needs_checkpoint_(needs_checkpoint), metadata_encrypted_(metadata_encrypted) {}
+ CheckpointManager(int needs_checkpoint = -1, bool metadata_encrypted = false,
+ bool needs_encrypt = false)
+ : needs_checkpoint_(needs_checkpoint),
+ metadata_encrypted_(metadata_encrypted),
+ needs_encrypt_(needs_encrypt) {}
bool NeedsCheckpoint() {
if (needs_checkpoint_ != UNKNOWN) {
@@ -1160,7 +1164,7 @@
} else {
LERROR << entry->fs_type << " does not implement checkpoints.";
}
- } else if (entry->fs_mgr_flags.checkpoint_blk) {
+ } else if (entry->fs_mgr_flags.checkpoint_blk && !needs_encrypt_) {
auto actual_block_device = block_device.empty() ? entry->blk_device : block_device;
if (fs_mgr_find_bow_device(actual_block_device).empty()) {
unique_fd fd(
@@ -1176,6 +1180,10 @@
return false;
}
+ // dm-bow will not load if size is not a multiple of 4096
+ // rounding down does not hurt, since ext4 will only use full blocks
+ size &= ~7;
+
android::dm::DmTable table;
auto bowTarget =
std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device);
@@ -1224,6 +1232,7 @@
enum { UNKNOWN = -1, NO = 0, YES = 1 };
int needs_checkpoint_;
bool metadata_encrypted_;
+ bool needs_encrypt_;
std::map<std::string, std::string> device_map_;
};
@@ -1841,17 +1850,14 @@
return ret;
}
-// If tmp_mount_point is non-null, mount the filesystem there. This is for the
-// tmp mount we do to check the user password
// If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
// in turn, and stop on 1st success, or no more match.
-static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
- const std::string& n_blk_device, const char* tmp_mount_point,
- int needs_checkpoint, bool metadata_encrypted) {
+int fs_mgr_do_mount(Fstab* fstab, const std::string& n_name, const std::string& n_blk_device,
+ int needs_checkpoint, bool needs_encrypt) {
int mount_errors = 0;
int first_mount_errno = 0;
std::string mount_point;
- CheckpointManager checkpoint_manager(needs_checkpoint, metadata_encrypted);
+ CheckpointManager checkpoint_manager(needs_checkpoint, true, needs_encrypt);
AvbUniquePtr avb_handle(nullptr);
if (!fstab) {
@@ -1893,11 +1899,7 @@
}
// Now mount it where requested */
- if (tmp_mount_point) {
- mount_point = tmp_mount_point;
- } else {
- mount_point = fstab_entry.mount_point;
- }
+ mount_point = fstab_entry.mount_point;
int fs_stat = prepare_fs_for_mount(n_blk_device, fstab_entry, mount_point);
@@ -1954,35 +1956,6 @@
return FS_MGR_DOMNT_FAILED;
}
-int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1, false);
-}
-
-int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
- bool needs_checkpoint, bool metadata_encrypted) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint,
- metadata_encrypted);
-}
-
-/*
- * mount a tmpfs filesystem at the given point.
- * return 0 on success, non-zero on failure.
- */
-int fs_mgr_do_tmpfs_mount(const char *n_name)
-{
- int ret;
-
- ret = mount("tmpfs", n_name, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV | MS_NOEXEC,
- CRYPTO_TMPFS_OPTIONS);
- if (ret < 0) {
- LERROR << "Cannot mount tmpfs filesystem at " << n_name;
- return -1;
- }
-
- /* Success */
- return 0;
-}
-
static bool ConfigureIoScheduler(const std::string& device_path) {
if (!StartsWith(device_path, "/dev/")) {
LERROR << __func__ << ": invalid argument " << device_path;
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 7189a71..c3c10ba 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -242,7 +242,9 @@
LWARNING << "Warning: zramsize= flag malformed: " << arg;
}
}
- } else if (StartsWith(flag, "fileencryption=")) {
+ } else if (StartsWith(flag, "fileencryption=") || flag == "fileencryption") {
+ // "fileencryption" enables file-based encryption. It's normally followed by an = and
+ // then the encryption options. But that can be omitted to use the default options.
ParseFileEncryption(arg, entry);
} else if (StartsWith(flag, "max_comp_streams=")) {
if (!ParseInt(arg, &entry->max_comp_streams)) {
@@ -304,19 +306,16 @@
if (!ParseByteCount(arg, &entry->zram_backingdev_size)) {
LWARNING << "Warning: zram_backingdev_size= flag malformed: " << arg;
}
- } else if (StartsWith(flag, "zoned_device=")) {
- std::string zoned;
- if (ReadFileToString("/sys/class/block/" + arg + "/queue/zoned", &zoned) &&
- android::base::StartsWith(zoned, "host-managed")) {
- entry->zoned_device = "/dev/block/" + arg;
+ } else if (flag == "zoned_device") {
+ if (access("/dev/block/by-name/zoned_device", F_OK) == 0) {
+ entry->zoned_device = "/dev/block/by-name/zoned_device";
// atgc in f2fs does not support a zoned device
auto options = Split(entry->fs_options, ",");
options.erase(std::remove(options.begin(), options.end(), "atgc"), options.end());
entry->fs_options = android::base::Join(options, ",");
- LINFO << "Removed ATGC in fs_options as " << entry->fs_options;
- } else {
- LWARNING << "Warning: cannot find the zoned device: " << arg;
+ LINFO << "Removed ATGC in fs_options as " << entry->fs_options
+ << " for zoned device=" << entry->zoned_device;
}
} else {
LWARNING << "Warning: unknown flag: " << flag;
@@ -488,13 +487,21 @@
return boot_devices;
}
-template <typename Pred>
-std::vector<FstabEntry*> GetEntriesByPred(Fstab* fstab, const Pred& pred) {
+// Helper class that maps Fstab* -> FstabEntry; const Fstab* -> const FstabEntry.
+template <typename FstabPtr>
+struct FstabPtrEntry {
+ using is_const_fstab = std::is_const<std::remove_pointer_t<FstabPtr>>;
+ using type = std::conditional_t<is_const_fstab::value, const FstabEntry, FstabEntry>;
+};
+
+template <typename FstabPtr, typename FstabPtrEntryType = typename FstabPtrEntry<FstabPtr>::type,
+ typename Pred>
+std::vector<FstabPtrEntryType*> GetEntriesByPred(FstabPtr fstab, const Pred& pred) {
if (fstab == nullptr) {
return {};
}
- std::vector<FstabEntry*> entries;
- for (auto&& entry : *fstab) {
+ std::vector<FstabPtrEntryType*> entries;
+ for (FstabPtrEntryType& entry : *fstab) {
if (pred(entry)) {
entries.push_back(&entry);
}
@@ -835,25 +842,27 @@
return !fstab->empty();
}
-FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path) {
- if (fstab == nullptr) {
- return nullptr;
- }
-
- for (auto& entry : *fstab) {
- if (entry.mount_point == path) {
- return &entry;
- }
- }
-
- return nullptr;
-}
-
std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path) {
return GetEntriesByPred(fstab,
[&path](const FstabEntry& entry) { return entry.mount_point == path; });
}
+std::vector<const FstabEntry*> GetEntriesForMountPoint(const Fstab* fstab,
+ const std::string& path) {
+ return GetEntriesByPred(fstab,
+ [&path](const FstabEntry& entry) { return entry.mount_point == path; });
+}
+
+FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path) {
+ std::vector<FstabEntry*> entries = GetEntriesForMountPoint(fstab, path);
+ return entries.empty() ? nullptr : entries.front();
+}
+
+const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& path) {
+ std::vector<const FstabEntry*> entries = GetEntriesForMountPoint(fstab, path);
+ return entries.empty() ? nullptr : entries.front();
+}
+
std::set<std::string> GetBootDevices() {
// First check bootconfig, then kernel commandline, then the device tree
std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index bb24abf..01827d6 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -116,8 +116,7 @@
// For non-A/B devices prefer cache backing storage if
// kPreferCacheBackingStorageProp property set.
- if (!IsABDevice() &&
- android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
+ if (!IsABDevice() && android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
return {kCacheMountPoint, kScratchMountPoint};
}
@@ -332,8 +331,14 @@
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 std::string& mount_point) {
+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 +
@@ -344,14 +349,14 @@
if (KernelSupportsUserXattrs()) {
ret += ",userxattr";
}
+ for (const auto& flag : android::base::Split(entry.fs_options, ",")) {
+ if (android::base::StartsWith(flag, "context=")) {
+ ret += "," + flag;
+ }
+ }
return ret;
}
-const std::string fs_mgr_mount_point(const std::string& mount_point) {
- if ("/"s != mount_point) return mount_point;
- return "/system";
-}
-
constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
class AutoSetFsCreateCon final {
@@ -710,8 +715,9 @@
return info;
}
-bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
- auto options = fs_mgr_get_overlayfs_options(mount_point);
+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;
@@ -933,7 +939,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;
@@ -1077,7 +1085,7 @@
return 0;
}
- auto ideal_size = std::min(super_info.size, (uint64_t(s.f_frsize) * s.f_bfree) / 2);
+ auto ideal_size = std::min(super_info.size, uint64_t(uint64_t(s.f_frsize) * s.f_bfree * 0.85));
// Align up to the filesystem block size.
if (auto remainder = ideal_size % s.f_bsize; remainder > 0) {
@@ -1346,12 +1354,13 @@
scratch_can_be_mounted = false;
TryMountScratch();
}
- ret &= fs_mgr_overlayfs_mount(mount_point);
+ ret &= fs_mgr_overlayfs_mount(entry);
}
return ret;
}
-bool fs_mgr_overlayfs_setup(const char* mount_point, bool* want_reboot, bool just_disabled_verity) {
+bool fs_mgr_overlayfs_setup(const Fstab& fstab, const char* mount_point, bool* want_reboot,
+ bool just_disabled_verity) {
if (!OverlayfsSetupAllowed(/*verbose=*/true)) {
return false;
}
@@ -1361,12 +1370,6 @@
return false;
}
- Fstab fstab;
- if (!ReadDefaultFstab(&fstab)) {
- LOG(ERROR) << "Could not read fstab";
- return false;
- }
-
auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
for (auto it = candidates.begin(); it != candidates.end();) {
if (mount_point &&
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 46f54cc..46cdb62 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -33,7 +33,7 @@
*/
#define FS_MGR_CHECK(x) CHECK(x) << "in libfs_mgr "
-#define FS_MGR_TAG "[libfs_mgr]"
+#define FS_MGR_TAG "[libfs_mgr] "
// Logs a message to kernel
#define LINFO LOG(INFO) << FS_MGR_TAG
diff --git a/fs_mgr/fs_mgr_priv_overlayfs.h b/fs_mgr/fs_mgr_priv_overlayfs.h
index 45b954d..2033701 100644
--- a/fs_mgr/fs_mgr_priv_overlayfs.h
+++ b/fs_mgr/fs_mgr_priv_overlayfs.h
@@ -29,8 +29,8 @@
//
// 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 char* mount_point = nullptr, bool* want_reboot = nullptr,
- bool just_disabled_verity = true);
+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,
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 23bc8e8..5a9f391 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -175,6 +175,8 @@
}
if (checkpointing) {
LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
+ LOG(ERROR) << "To force end checkpointing, call 'vdc checkpoint commitChanges'";
+ LOG(ERROR) << "Warning: this can lead to data corruption if rolled back.";
return false;
}
return true;
@@ -289,7 +291,7 @@
if (fs_mgr_wants_overlayfs(&entry)) {
bool want_reboot = false;
bool force = result->disabled_verity;
- if (!fs_mgr_overlayfs_setup(mount_point.c_str(), &want_reboot, force)) {
+ if (!fs_mgr_overlayfs_setup(*partitions, mount_point.c_str(), &want_reboot, force)) {
LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
ok = false;
it = partitions->erase(it);
@@ -442,7 +444,12 @@
bool SetupOrTeardownOverlayfs(bool enable) {
bool want_reboot = false;
if (enable) {
- if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ LOG(ERROR) << "Could not read fstab.";
+ return want_reboot;
+ }
+ if (!fs_mgr_overlayfs_setup(fstab, nullptr, &want_reboot)) {
LOG(ERROR) << "Overlayfs setup failed.";
return want_reboot;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 43de6d8..bc4a7a6 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -85,13 +85,10 @@
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
#define FS_MGR_DOMNT_SUCCESS 0
-int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
- char* tmp_mount_point);
-int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
- char* tmp_mount_point, bool need_cp, bool metadata_encrypted);
+int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const std::string& n_name,
+ const std::string& n_blk_device, int needs_checkpoint, bool needs_encrypt);
int fs_mgr_do_mount_one(const android::fs_mgr::FstabEntry& entry,
const std::string& mount_point = "");
-int fs_mgr_do_tmpfs_mount(const char *n_name);
bool fs_mgr_load_verity_state(int* mode);
// Returns true if verity is enabled on this particular FstabEntry.
bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 124f070..a914b53 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -105,10 +105,13 @@
bool ReadDefaultFstab(Fstab* fstab);
bool SkipMountingPartitions(Fstab* fstab, bool verbose = false);
-FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
// The Fstab can contain multiple entries for the same mount point with different configurations.
std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path);
+// Like GetEntriesForMountPoint() but return only the first entry or nullptr if no entry is found.
+FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
+const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& path);
+
// This method builds DSU fstab entries and transfer the fstab.
//
// fstab points to the unmodified fstab.
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 2bb9035..5cc0346 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -90,19 +90,3 @@
min_shipping_api_level: 29,
},
}
-
-cc_fuzz {
- name: "dm_linear_table_fuzzer",
- defaults: ["fs_mgr_defaults"],
- srcs: [
- "dm_linear_fuzzer.cpp",
- "test_util.cpp",
- ],
- static_libs: [
- "libdm",
- "libbase",
- "libext2_uuid",
- "libfs_mgr",
- "liblog",
- ],
-}
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 4034e30..3a9ed9b 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -20,6 +20,7 @@
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <chrono>
#include <functional>
@@ -105,6 +106,10 @@
if (!GetDeviceUniquePath(name, &unique_path)) {
LOG(ERROR) << "Failed to get unique path for device " << name;
}
+ // Expect to have uevent generated if the unique path actually exists. This may not exist
+ // if the device was created but has never been activated before it gets deleted.
+ bool need_uevent = !unique_path.empty() && access(unique_path.c_str(), F_OK) == 0;
+
struct dm_ioctl io;
InitIo(&io, name);
@@ -115,7 +120,7 @@
// Check to make sure appropriate uevent is generated so ueventd will
// do the right thing and remove the corresponding device node and symlinks.
- if ((io.flags & DM_UEVENT_GENERATED_FLAG) == 0) {
+ if (need_uevent && (io.flags & DM_UEVENT_GENERATED_FLAG) == 0) {
LOG(ERROR) << "Didn't generate uevent for [" << name << "] removal";
return false;
}
@@ -242,6 +247,25 @@
return true;
}
+bool DeviceMapper::GetDeviceNameAndUuid(dev_t dev, std::string* name, std::string* uuid) {
+ struct dm_ioctl io;
+ InitIo(&io, {});
+ io.dev = dev;
+
+ if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
+ PLOG(ERROR) << "Failed to find device dev: " << major(dev) << ":" << minor(dev);
+ return false;
+ }
+
+ if (name) {
+ *name = io.name;
+ }
+ if (uuid) {
+ *uuid = io.uuid;
+ }
+ return true;
+}
+
std::optional<DeviceMapper::Info> DeviceMapper::GetDetailedInfo(const std::string& name) const {
struct dm_ioctl io;
InitIo(&io, name);
@@ -289,7 +313,7 @@
return true;
}
-bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable& table) {
+bool DeviceMapper::LoadTable(const std::string& name, const DmTable& table) {
std::string ioctl_buffer(sizeof(struct dm_ioctl), 0);
ioctl_buffer += table.Serialize();
@@ -305,9 +329,17 @@
PLOG(ERROR) << "DM_TABLE_LOAD failed";
return false;
}
+ return true;
+}
- InitIo(io, name);
- if (ioctl(fd_, DM_DEV_SUSPEND, io)) {
+bool DeviceMapper::LoadTableAndActivate(const std::string& name, const DmTable& table) {
+ if (!LoadTable(name, table)) {
+ return false;
+ }
+
+ struct dm_ioctl io;
+ InitIo(&io, name);
+ if (ioctl(fd_, DM_DEV_SUSPEND, &io)) {
PLOG(ERROR) << "DM_TABLE_SUSPEND resume failed";
return false;
}
@@ -703,5 +735,28 @@
return dm_block_devices;
}
+bool DeviceMapper::CreatePlaceholderDevice(const std::string& name) {
+ if (!CreateEmptyDevice(name)) {
+ return false;
+ }
+
+ struct utsname uts;
+ unsigned int major, minor;
+ if (uname(&uts) != 0 || sscanf(uts.release, "%u.%u", &major, &minor) != 2) {
+ LOG(ERROR) << "Could not parse the kernel version from uname";
+ return true;
+ }
+
+ // On Linux 5.15+, there is no uevent until DM_TABLE_LOAD.
+ if (major > 5 || (major == 5 && minor >= 15)) {
+ DmTable table;
+ table.Emplace<DmTargetError>(0, 1);
+ if (!LoadTable(name, table)) {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libdm/dm_linear_fuzzer.cpp b/fs_mgr/libdm/dm_linear_fuzzer.cpp
deleted file mode 100644
index 8462901..0000000
--- a/fs_mgr/libdm/dm_linear_fuzzer.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <chrono>
-
-#include <android-base/file.h>
-#include <android-base/unique_fd.h>
-#include <libdm/dm_table.h>
-#include <libdm/loop_control.h>
-
-#include "test_util.h"
-
-using namespace android;
-using namespace android::base;
-using namespace android::dm;
-using namespace std;
-using namespace std::chrono_literals;
-
-/*
- * This test aims at making the library crash, so these functions are not
- * really useful.
- * Keeping them here for future use.
- */
-template <class T, class C>
-void ASSERT_EQ(const T& /*a*/, const C& /*b*/) {
- // if (a != b) {}
-}
-
-template <class T>
-void ASSERT_FALSE(const T& /*a*/) {
- // if (a) {}
-}
-
-template <class T, class C>
-void ASSERT_GE(const T& /*a*/, const C& /*b*/) {
- // if (a < b) {}
-}
-
-template <class T, class C>
-void ASSERT_NE(const T& /*a*/, const C& /*b*/) {
- // if (a == b) {}
-}
-
-template <class T>
-void ASSERT_TRUE(const T& /*a*/) {
- // if (!a) {}
-}
-
-template <class T, class C>
-void EXPECT_EQ(const T& a, const C& b) {
- ASSERT_EQ(a, b);
-}
-
-template <class T>
-void EXPECT_TRUE(const T& a) {
- ASSERT_TRUE(a);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- uint64_t val[6];
-
- if (size != sizeof(val)) {
- return 0;
- }
-
- memcpy(&val, &data[0], sizeof(*val));
-
- unique_fd tmp1(CreateTempFile("file_1", 4096));
- ASSERT_GE(tmp1, 0);
- unique_fd tmp2(CreateTempFile("file_2", 4096));
- ASSERT_GE(tmp2, 0);
-
- LoopDevice loop_a(tmp1, 10s);
- ASSERT_TRUE(loop_a.valid());
- LoopDevice loop_b(tmp2, 10s);
- ASSERT_TRUE(loop_b.valid());
-
- // Define a 2-sector device, with each sector mapping to the first sector
- // of one of our loop devices.
- DmTable table;
- ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[0], val[1], loop_a.device(), val[2]));
- ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[3], val[4], loop_b.device(), val[5]));
- ASSERT_TRUE(table.valid());
- ASSERT_EQ(2u, table.num_sectors());
-
- TempDevice dev("libdm-test-dm-linear", table);
- ASSERT_TRUE(dev.valid());
- ASSERT_FALSE(dev.path().empty());
-
- auto& dm = DeviceMapper::Instance();
-
- dev_t dev_number;
- ASSERT_TRUE(dm.GetDeviceNumber(dev.name(), &dev_number));
- ASSERT_NE(dev_number, 0);
-
- std::string dev_string;
- ASSERT_TRUE(dm.GetDeviceString(dev.name(), &dev_string));
- ASSERT_FALSE(dev_string.empty());
-
- // Test GetTableStatus.
- vector<DeviceMapper::TargetInfo> targets;
- ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
- ASSERT_EQ(targets.size(), 2);
- EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
- EXPECT_TRUE(targets[0].data.empty());
- EXPECT_EQ(targets[0].spec.sector_start, 0);
- EXPECT_EQ(targets[0].spec.length, 1);
- EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
- EXPECT_TRUE(targets[1].data.empty());
- EXPECT_EQ(targets[1].spec.sector_start, 1);
- EXPECT_EQ(targets[1].spec.length, 1);
-
- // Test GetTargetType().
- EXPECT_EQ(DeviceMapper::GetTargetType(targets[0].spec), std::string{"linear"});
- EXPECT_EQ(DeviceMapper::GetTargetType(targets[1].spec), std::string{"linear"});
-
- // Normally the TestDevice destructor would delete this, but at least one
- // test should ensure that device deletion works.
- ASSERT_TRUE(dev.Destroy());
-
- return 0;
-}
diff --git a/fs_mgr/libdm/dm_table.cpp b/fs_mgr/libdm/dm_table.cpp
index efe03ab..b546995 100644
--- a/fs_mgr/libdm/dm_table.cpp
+++ b/fs_mgr/libdm/dm_table.cpp
@@ -38,11 +38,11 @@
bool DmTable::valid() const {
if (targets_.empty()) {
LOG(ERROR) << "Device-mapper table must have at least one target.";
- return "";
+ return false;
}
if (targets_[0]->start() != 0) {
LOG(ERROR) << "Device-mapper table must start at logical sector 0.";
- return "";
+ return false;
}
return true;
}
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index 541f254..c522eaf 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <time.h>
#include <unistd.h>
@@ -29,6 +30,7 @@
#include <thread>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@@ -41,16 +43,40 @@
using namespace std;
using namespace std::chrono_literals;
using namespace android::dm;
-using unique_fd = android::base::unique_fd;
+using android::base::make_scope_guard;
+using android::base::unique_fd;
-TEST(libdm, HasMinimumTargets) {
+class DmTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ const testing::TestInfo* const test_info =
+ testing::UnitTest::GetInstance()->current_test_info();
+ test_name_ = test_info->name();
+ test_full_name_ = test_info->test_suite_name() + "/"s + test_name_;
+
+ LOG(INFO) << "Starting test: " << test_full_name_;
+ }
+ void TearDown() override {
+ LOG(INFO) << "Tearing down test: " << test_full_name_;
+
+ auto& dm = DeviceMapper::Instance();
+ ASSERT_TRUE(dm.DeleteDeviceIfExists(test_name_));
+
+ LOG(INFO) << "Teardown complete for test: " << test_full_name_;
+ }
+
+ std::string test_name_;
+ std::string test_full_name_;
+};
+
+TEST_F(DmTest, HasMinimumTargets) {
DmTargetTypeInfo info;
DeviceMapper& dm = DeviceMapper::Instance();
ASSERT_TRUE(dm.GetTargetByName("linear", &info));
}
-TEST(libdm, DmLinear) {
+TEST_F(DmTest, DmLinear) {
unique_fd tmp1(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp1, 0);
unique_fd tmp2(CreateTempFile("file_2", 4096));
@@ -126,7 +152,7 @@
ASSERT_TRUE(dev.Destroy());
}
-TEST(libdm, DmSuspendResume) {
+TEST_F(DmTest, DmSuspendResume) {
unique_fd tmp1(CreateTempFile("file_suspend_resume", 512));
ASSERT_GE(tmp1, 0);
@@ -155,7 +181,7 @@
ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE);
}
-TEST(libdm, DmVerityArgsAvb2) {
+TEST_F(DmTest, DmVerityArgsAvb2) {
std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a";
std::string algorithm = "sha1";
std::string digest = "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21";
@@ -177,7 +203,7 @@
EXPECT_EQ(target.GetParameterString(), expected);
}
-TEST(libdm, DmSnapshotArgs) {
+TEST_F(DmTest, DmSnapshotArgs) {
DmTargetSnapshot target1(0, 512, "base", "cow", SnapshotStorageMode::Persistent, 8);
if (DmTargetSnapshot::ReportsOverflow("snapshot")) {
EXPECT_EQ(target1.GetParameterString(), "base cow PO 8");
@@ -199,7 +225,7 @@
EXPECT_EQ(target3.name(), "snapshot-merge");
}
-TEST(libdm, DmSnapshotOriginArgs) {
+TEST_F(DmTest, DmSnapshotOriginArgs) {
DmTargetSnapshotOrigin target(0, 512, "base");
EXPECT_EQ(target.GetParameterString(), "base");
EXPECT_EQ(target.name(), "snapshot-origin");
@@ -329,7 +355,7 @@
return true;
}
-TEST(libdm, DmSnapshot) {
+TEST_F(DmTest, DmSnapshot) {
if (!CheckSnapshotAvailability()) {
return;
}
@@ -373,7 +399,7 @@
ASSERT_EQ(read, data);
}
-TEST(libdm, DmSnapshotOverflow) {
+TEST_F(DmTest, DmSnapshotOverflow) {
if (!CheckSnapshotAvailability()) {
return;
}
@@ -420,7 +446,7 @@
}
}
-TEST(libdm, ParseStatusText) {
+TEST_F(DmTest, ParseStatusText) {
DmTargetSnapshot::Status status;
// Bad inputs
@@ -447,7 +473,7 @@
EXPECT_TRUE(DmTargetSnapshot::ParseStatusText("Overflow", &status));
}
-TEST(libdm, DmSnapshotMergePercent) {
+TEST_F(DmTest, DmSnapshotMergePercent) {
DmTargetSnapshot::Status status;
// Correct input
@@ -501,7 +527,7 @@
EXPECT_LE(DmTargetSnapshot::MergePercent(status, 0), 0.0);
}
-TEST(libdm, CryptArgs) {
+TEST_F(DmTest, CryptArgs) {
DmTargetCrypt target1(0, 512, "sha1", "abcdefgh", 50, "/dev/loop0", 100);
ASSERT_EQ(target1.name(), "crypt");
ASSERT_TRUE(target1.Valid());
@@ -517,7 +543,7 @@
"iv_large_sectors sector_size:64");
}
-TEST(libdm, DefaultKeyArgs) {
+TEST_F(DmTest, DefaultKeyArgs) {
DmTargetDefaultKey target(0, 4096, "aes-xts-plain64", "abcdef0123456789", "/dev/loop0", 0);
target.SetSetDun();
ASSERT_EQ(target.name(), "default-key");
@@ -528,7 +554,7 @@
"iv_large_sectors");
}
-TEST(libdm, DefaultKeyLegacyArgs) {
+TEST_F(DmTest, DefaultKeyLegacyArgs) {
DmTargetDefaultKey target(0, 4096, "AES-256-XTS", "abcdef0123456789", "/dev/loop0", 0);
target.SetUseLegacyOptionsFormat();
ASSERT_EQ(target.name(), "default-key");
@@ -536,7 +562,7 @@
ASSERT_EQ(target.GetParameterString(), "AES-256-XTS abcdef0123456789 /dev/loop0 0");
}
-TEST(libdm, DeleteDeviceWithTimeout) {
+TEST_F(DmTest, DeleteDeviceWithTimeout) {
unique_fd tmp(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp, 0);
LoopDevice loop(tmp, 10s);
@@ -560,7 +586,7 @@
ASSERT_EQ(ENOENT, errno);
}
-TEST(libdm, IsDmBlockDevice) {
+TEST_F(DmTest, IsDmBlockDevice) {
unique_fd tmp(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp, 0);
LoopDevice loop(tmp, 10s);
@@ -579,7 +605,7 @@
ASSERT_FALSE(dm.IsDmBlockDevice(loop.device()));
}
-TEST(libdm, GetDmDeviceNameByPath) {
+TEST_F(DmTest, GetDmDeviceNameByPath) {
unique_fd tmp(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp, 0);
LoopDevice loop(tmp, 10s);
@@ -600,7 +626,7 @@
ASSERT_EQ("libdm-test-dm-linear", *name);
}
-TEST(libdm, GetParentBlockDeviceByPath) {
+TEST_F(DmTest, GetParentBlockDeviceByPath) {
unique_fd tmp(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp, 0);
LoopDevice loop(tmp, 10s);
@@ -620,7 +646,7 @@
ASSERT_EQ(loop.device(), *sub_block_device);
}
-TEST(libdm, DeleteDeviceDeferredNoReferences) {
+TEST_F(DmTest, DeleteDeviceDeferredNoReferences) {
unique_fd tmp(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp, 0);
LoopDevice loop(tmp, 10s);
@@ -646,7 +672,7 @@
ASSERT_EQ(ENOENT, errno);
}
-TEST(libdm, DeleteDeviceDeferredWaitsForLastReference) {
+TEST_F(DmTest, DeleteDeviceDeferredWaitsForLastReference) {
unique_fd tmp(CreateTempFile("file_1", 4096));
ASSERT_GE(tmp, 0);
LoopDevice loop(tmp, 10s);
@@ -681,7 +707,7 @@
ASSERT_EQ(ENOENT, errno);
}
-TEST(libdm, CreateEmptyDevice) {
+TEST_F(DmTest, CreateEmptyDevice) {
DeviceMapper& dm = DeviceMapper::Instance();
ASSERT_TRUE(dm.CreateEmptyDevice("empty-device"));
auto guard =
@@ -690,3 +716,44 @@
// Empty device should be in suspended state.
ASSERT_EQ(DmDeviceState::SUSPENDED, dm.GetState("empty-device"));
}
+
+TEST_F(DmTest, UeventAfterLoadTable) {
+ struct utsname u;
+ ASSERT_EQ(uname(&u), 0);
+
+ unsigned int major, minor;
+ ASSERT_EQ(sscanf(u.release, "%u.%u", &major, &minor), 2);
+
+ if (major < 5 || (major == 5 && minor < 15)) {
+ GTEST_SKIP() << "Skipping test on kernel < 5.15";
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ ASSERT_TRUE(dm.CreateEmptyDevice(test_name_));
+
+ DmTable table;
+ table.Emplace<DmTargetError>(0, 1);
+ ASSERT_TRUE(dm.LoadTable(test_name_, table));
+
+ std::string ignore_path;
+ ASSERT_TRUE(dm.WaitForDevice(test_name_, 5s, &ignore_path));
+
+ auto info = dm.GetDetailedInfo(test_name_);
+ ASSERT_TRUE(info.has_value());
+ ASSERT_TRUE(info->IsSuspended());
+
+ ASSERT_TRUE(dm.DeleteDevice(test_name_));
+}
+
+TEST_F(DmTest, GetNameAndUuid) {
+ auto& dm = DeviceMapper::Instance();
+ ASSERT_TRUE(dm.CreatePlaceholderDevice(test_name_));
+
+ dev_t dev;
+ ASSERT_TRUE(dm.GetDeviceNumber(test_name_, &dev));
+
+ std::string name, uuid;
+ ASSERT_TRUE(dm.GetDeviceNameAndUuid(dev, &name, &uuid));
+ ASSERT_EQ(name, test_name_);
+ ASSERT_FALSE(uuid.empty());
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 1057d7f..3e7ecc6 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -75,6 +75,7 @@
const std::chrono::milliseconds& timeout_ms) = 0;
virtual DmDeviceState GetState(const std::string& name) const = 0;
virtual bool LoadTableAndActivate(const std::string& name, const DmTable& table) = 0;
+ virtual bool LoadTable(const std::string& name, const DmTable& table) = 0;
virtual bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) = 0;
virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) = 0;
virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) = 0;
@@ -116,7 +117,7 @@
bool IsBufferFull() const { return flags_ & DM_BUFFER_FULL_FLAG; }
bool IsInactiveTablePresent() const { return flags_ & DM_INACTIVE_PRESENT_FLAG; }
bool IsReadOnly() const { return flags_ & DM_READONLY_FLAG; }
- bool IsSuspended() const { return flags_ & DM_SUSPEND_FLAG; }
+ bool IsSuspended() const { return !IsActiveTablePresent() || (flags_ & DM_SUSPEND_FLAG); }
};
// Removes a device mapper device with the given name.
@@ -199,6 +200,12 @@
// Returns 'true' on success, false otherwise.
bool LoadTableAndActivate(const std::string& name, const DmTable& table) override;
+ // Same as LoadTableAndActivate, but there is no resume step. This puts the
+ // new table in the inactive slot.
+ //
+ // Returns 'true' on success, false otherwise.
+ bool LoadTable(const std::string& name, const DmTable& table) override;
+
// Returns true if a list of available device mapper targets registered in the kernel was
// successfully read and stored in 'targets'. Returns 'false' otherwise.
bool GetAvailableTargets(std::vector<DmTargetTypeInfo>* targets);
@@ -285,6 +292,14 @@
// Returns mapping <partition-name, /dev/block/dm-x>
std::map<std::string, std::string> FindDmPartitions();
+ // Create a placeholder device. This is useful for ensuring that a uevent is in the pipeline,
+ // to reduce the amount of time a future WaitForDevice will block. On kernels < 5.15, this
+ // simply calls CreateEmptyDevice. On 5.15 and higher, it also loads (but does not activate)
+ // a placeholder table containing dm-error.
+ bool CreatePlaceholderDevice(const std::string& name);
+
+ bool GetDeviceNameAndUuid(dev_t dev, std::string* name, std::string* uuid);
+
private:
// Maximum possible device mapper targets registered in the kernel.
// This is only used to read the list of targets from kernel so we allocate
diff --git a/fs_mgr/libdm/include/libdm/dm_table.h b/fs_mgr/libdm/include/libdm/dm_table.h
index ee66653..427f34d 100644
--- a/fs_mgr/libdm/include/libdm/dm_table.h
+++ b/fs_mgr/libdm/include/libdm/dm_table.h
@@ -31,6 +31,7 @@
class DmTable {
public:
DmTable() : num_sectors_(0), readonly_(false) {}
+ DmTable(DmTable&& other) = default;
// Adds a target to the device mapper table for a range specified in the target object.
// The function will return 'true' if the target was successfully added and doesn't overlap with
@@ -70,6 +71,8 @@
void set_readonly(bool readonly) { readonly_ = readonly; }
bool readonly() const { return readonly_; }
+ DmTable& operator=(DmTable&& other) = default;
+
~DmTable() = default;
private:
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 9543058..09fe200 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -323,6 +323,14 @@
std::string control_device_;
};
+class DmTargetError final : public DmTarget {
+ public:
+ DmTargetError(uint64_t start, uint64_t length) : DmTarget(start, length) {}
+
+ std::string name() const override { return "error"; }
+ std::string GetParameterString() const override { return ""; }
+};
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index 5deba65..ddda648 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -93,6 +93,9 @@
test_options: {
min_shipping_api_level: 29,
},
+ header_libs: [
+ "libstorage_literals_headers",
+ ],
require_root: true,
}
diff --git a/fs_mgr/libfiemap/README.md b/fs_mgr/libfiemap/README.md
index 62d610a..cdc80b2 100644
--- a/fs_mgr/libfiemap/README.md
+++ b/fs_mgr/libfiemap/README.md
@@ -35,18 +35,18 @@
We break the problem down into three scenarios.
-### FDE and Metadata Encrypted Devices
+### Metadata Encrypted Devices
-When FDE or metadata encryption is used, `/data` is not mounted from
+When metadata encryption is used, `/data` is not mounted from
`/dev/block/by-name/data`. Instead, it is mounted from an intermediate
-`dm-crypt` or `dm-default-key` device. This means the underlying device is
-not marked in use, and we can create new dm-linear devices on top of it.
+`dm-default-key` device. This means the underlying device is not marked in use,
+and we can create new dm-linear devices on top of it.
On these devices, a block device for an image will consist of a single
device-mapper device with a `dm-linear` table entry for each extent in the
backing file.
-### Unencrypted and FBE-encrypted Devices
+### Unencrypted and FBE-only Devices
When a device is unencrypted, or is encrypted with FBE but not metadata
encryption, we instead use a loop device with `LOOP_SET_DIRECT_IO` enabled.
diff --git a/fs_mgr/libfiemap/fiemap_writer.cpp b/fs_mgr/libfiemap/fiemap_writer.cpp
index 275388e..06e210e 100644
--- a/fs_mgr/libfiemap/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer.cpp
@@ -458,9 +458,34 @@
return FiemapStatus::Error();
}
- if (fallocate(file_fd, 0, 0, file_size)) {
- PLOG(ERROR) << "Failed to allocate space for file: " << file_path << " size: " << file_size;
- return FiemapStatus::FromErrno(errno);
+ // F2FS can return EAGAIN and partially fallocate. Keep trying to fallocate,
+ // and if we don't make forward progress, return ENOSPC.
+ std::optional<off_t> prev_size;
+ while (true) {
+ if (fallocate(file_fd, 0, 0, file_size) == 0) {
+ break;
+ }
+ if (errno != EAGAIN) {
+ PLOG(ERROR) << "Failed to allocate space for file: " << file_path
+ << " size: " << file_size;
+ return FiemapStatus::FromErrno(errno);
+ }
+
+ struct stat s;
+ if (fstat(file_fd, &s) < 0) {
+ PLOG(ERROR) << "Failed to fstat after fallocate failure: " << file_path;
+ return FiemapStatus::FromErrno(errno);
+ }
+ if (!prev_size) {
+ prev_size = {s.st_size};
+ continue;
+ }
+ if (*prev_size >= s.st_size) {
+ LOG(ERROR) << "Fallocate retry failed, got " << s.st_size << ", asked for "
+ << file_size;
+ return FiemapStatus(FiemapStatus::ErrorCode::NO_SPACE);
+ }
+ LOG(INFO) << "Retrying fallocate, got " << s.st_size << ", asked for " << file_size;
}
if (need_explicit_writes) {
diff --git a/fs_mgr/libfiemap/fiemap_writer_test.cpp b/fs_mgr/libfiemap/fiemap_writer_test.cpp
index c65481b..bd97a78 100644
--- a/fs_mgr/libfiemap/fiemap_writer_test.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer_test.cpp
@@ -22,21 +22,25 @@
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>
#include <string>
+#include <utility>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
+#include <fstab/fstab.h>
#include <gtest/gtest.h>
#include <libdm/loop_control.h>
#include <libfiemap/fiemap_writer.h>
#include <libfiemap/split_fiemap_writer.h>
#include <libgsi/libgsi.h>
+#include <storage_literals/storage_literals.h>
#include "utility.h"
@@ -46,6 +50,7 @@
using namespace std;
using namespace std::string_literals;
using namespace android::fiemap;
+using namespace android::storage_literals;
using unique_fd = android::base::unique_fd;
using LoopDevice = android::dm::LoopDevice;
@@ -427,90 +432,123 @@
ASSERT_FALSE(ptr->Write(buffer.get(), kSize));
}
-class VerifyBlockWritesExt4 : public ::testing::Test {
+// Get max file size and free space.
+std::pair<uint64_t, uint64_t> GetBigFileLimit(const std::string& mount_point) {
+ struct statvfs fs;
+ if (statvfs(mount_point.c_str(), &fs) < 0) {
+ PLOG(ERROR) << "statfs failed";
+ return {0, 0};
+ }
+
+ auto fs_limit = static_cast<uint64_t>(fs.f_blocks) * (fs.f_bsize - 1);
+ auto fs_free = static_cast<uint64_t>(fs.f_bfree) * fs.f_bsize;
+
+ LOG(INFO) << "Big file limit: " << fs_limit << ", free space: " << fs_free;
+
+ return {fs_limit, fs_free};
+}
+
+class FsTest : public ::testing::Test {
+ protected:
// 2GB Filesystem and 4k block size by default
static constexpr uint64_t block_size = 4096;
- static constexpr uint64_t fs_size = 2147483648;
+ static constexpr uint64_t fs_size = 64 * 1024 * 1024;
- protected:
- void SetUp() override {
- fs_path = std::string(getenv("TMPDIR")) + "/ext4_2G.img";
+ void SetUp() {
+ android::fs_mgr::Fstab fstab;
+ ASSERT_TRUE(android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab));
+
+ ASSERT_EQ(access(tmpdir_.path, F_OK), 0);
+ fs_path_ = tmpdir_.path + "/fs_image"s;
+ mntpoint_ = tmpdir_.path + "/mnt_point"s;
+
+ auto entry = android::fs_mgr::GetEntryForMountPoint(&fstab, "/data");
+ ASSERT_NE(entry, nullptr);
+ if (entry->fs_type == "ext4") {
+ SetUpExt4();
+ } else if (entry->fs_type == "f2fs") {
+ SetUpF2fs();
+ } else {
+ FAIL() << "Unrecognized fs_type: " << entry->fs_type;
+ }
+ }
+
+ void SetUpExt4() {
uint64_t count = fs_size / block_size;
std::string dd_cmd =
::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64
" count=%" PRIu64 " > /dev/null 2>&1",
- fs_path.c_str(), block_size, count);
+ fs_path_.c_str(), block_size, count);
std::string mkfs_cmd =
- ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path.c_str());
+ ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path_.c_str());
// create mount point
- mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt";
- ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0);
+ ASSERT_EQ(mkdir(mntpoint_.c_str(), S_IRWXU), 0);
// create file for the file system
int ret = system(dd_cmd.c_str());
ASSERT_EQ(ret, 0);
// Get and attach a loop device to the filesystem we created
- LoopDevice loop_dev(fs_path, 10s);
+ LoopDevice loop_dev(fs_path_, 10s);
ASSERT_TRUE(loop_dev.valid());
// create file system
ret = system(mkfs_cmd.c_str());
ASSERT_EQ(ret, 0);
// mount the file system
- ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0);
+ ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint_.c_str(), "ext4", 0, nullptr), 0);
}
- void TearDown() override {
- umount(mntpoint.c_str());
- rmdir(mntpoint.c_str());
- unlink(fs_path.c_str());
- }
-
- std::string mntpoint;
- std::string fs_path;
-};
-
-class VerifyBlockWritesF2fs : public ::testing::Test {
- // 2GB Filesystem and 4k block size by default
- static constexpr uint64_t block_size = 4096;
- static constexpr uint64_t fs_size = 2147483648;
-
- protected:
- void SetUp() override {
- fs_path = std::string(getenv("TMPDIR")) + "/f2fs_2G.img";
+ void SetUpF2fs() {
uint64_t count = fs_size / block_size;
std::string dd_cmd =
::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64
" count=%" PRIu64 " > /dev/null 2>&1",
- fs_path.c_str(), block_size, count);
+ fs_path_.c_str(), block_size, count);
std::string mkfs_cmd =
- ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path.c_str());
+ ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path_.c_str());
// create mount point
- mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt";
- ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0);
+ ASSERT_EQ(mkdir(mntpoint_.c_str(), S_IRWXU), 0);
// create file for the file system
int ret = system(dd_cmd.c_str());
ASSERT_EQ(ret, 0);
// Get and attach a loop device to the filesystem we created
- LoopDevice loop_dev(fs_path, 10s);
+ LoopDevice loop_dev(fs_path_, 10s);
ASSERT_TRUE(loop_dev.valid());
// create file system
ret = system(mkfs_cmd.c_str());
ASSERT_EQ(ret, 0);
// mount the file system
- ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0);
+ ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint_.c_str(), "f2fs", 0, nullptr), 0);
}
void TearDown() override {
- umount(mntpoint.c_str());
- rmdir(mntpoint.c_str());
- unlink(fs_path.c_str());
+ umount(mntpoint_.c_str());
+ rmdir(mntpoint_.c_str());
+ unlink(fs_path_.c_str());
}
- std::string mntpoint;
- std::string fs_path;
+ TemporaryDir tmpdir_;
+ std::string mntpoint_;
+ std::string fs_path_;
};
+TEST_F(FsTest, LowSpaceError) {
+ auto limits = GetBigFileLimit(mntpoint_);
+ ASSERT_GE(limits.first, 0);
+
+ FiemapUniquePtr ptr;
+
+ auto test_file = mntpoint_ + "/big_file";
+ auto status = FiemapWriter::Open(test_file, limits.first, &ptr);
+ ASSERT_FALSE(status.is_ok());
+ ASSERT_EQ(status.error_code(), FiemapStatus::ErrorCode::NO_SPACE);
+
+ // Also test for EFBIG.
+ status = FiemapWriter::Open(test_file, 16_TiB, &ptr);
+ ASSERT_FALSE(status.is_ok());
+ ASSERT_NE(status.error_code(), FiemapStatus::ErrorCode::NO_SPACE);
+}
+
bool DetermineBlockSize() {
struct statfs s;
if (statfs(gTestDir.c_str(), &s)) {
diff --git a/fs_mgr/libfiemap/include/libfiemap/fiemap_status.h b/fs_mgr/libfiemap/include/libfiemap/fiemap_status.h
index d7b2cf1..1365ba4 100644
--- a/fs_mgr/libfiemap/include/libfiemap/fiemap_status.h
+++ b/fs_mgr/libfiemap/include/libfiemap/fiemap_status.h
@@ -56,8 +56,7 @@
// For logging and debugging only.
std::string string() const;
- protected:
- FiemapStatus(ErrorCode code) : error_code_(code) {}
+ explicit FiemapStatus(ErrorCode code) : error_code_(code) {}
private:
ErrorCode error_code_;
diff --git a/fs_mgr/libfiemap/metadata.cpp b/fs_mgr/libfiemap/metadata.cpp
index b0dfb5c..22b8afb 100644
--- a/fs_mgr/libfiemap/metadata.cpp
+++ b/fs_mgr/libfiemap/metadata.cpp
@@ -30,6 +30,7 @@
namespace fiemap {
using namespace android::fs_mgr;
+using android::base::unique_fd;
static constexpr uint32_t kMaxMetadataSize = 256 * 1024;
@@ -109,10 +110,18 @@
if (exported->partitions.empty() && android::base::RemoveFileIfExists(metadata_file)) {
return true;
}
- if (!WriteToImageFile(metadata_file, *exported.get())) {
+
+ unique_fd fd(open(metadata_file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY | O_SYNC, 0644));
+ if (fd < 0) {
+ LOG(ERROR) << "open failed: " << metadata_file;
+ return false;
+ }
+
+ if (!WriteToImageFile(fd, *exported.get())) {
LOG(ERROR) << "Unable to save new metadata";
return false;
}
+
return true;
}
diff --git a/fs_mgr/libfs_avb/avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp
index 46072bb..a119bfc 100644
--- a/fs_mgr/libfs_avb/avb_ops.cpp
+++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -26,8 +26,10 @@
#include <errno.h>
#include <fcntl.h>
+#include <linux/fs.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/stat.h>
#include <string>
@@ -96,13 +98,11 @@
return AVB_IO_RESULT_OK;
}
-static AvbIOResult no_op_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED,
- const char* partition ATTRIBUTE_UNUSED,
- uint64_t* out_size_num_byte) {
- // The function is for bootloader to load entire content of AVB HASH partitions.
- // In user-space, returns 0 as we only need to set up AVB HASHTHREE partitions.
- *out_size_num_byte = 0;
- return AVB_IO_RESULT_OK;
+static AvbIOResult get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED,
+ const char* partition ATTRIBUTE_UNUSED,
+ uint64_t* out_size_num_byte) {
+ return FsManagerAvbOps::GetInstanceFromAvbOps(ops)->GetSizeOfPartition(partition,
+ out_size_num_byte);
}
// Converts a partition name (with ab_suffix) to the corresponding mount point.
@@ -131,7 +131,7 @@
avb_ops_.validate_vbmeta_public_key = no_op_validate_vbmeta_public_key;
avb_ops_.read_is_device_unlocked = no_op_read_is_device_unlocked;
avb_ops_.get_unique_guid_for_partition = no_op_get_unique_guid_for_partition;
- avb_ops_.get_size_of_partition = no_op_get_size_of_partition;
+ avb_ops_.get_size_of_partition = get_size_of_partition;
// Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
avb_ops_.user_data = this;
@@ -167,13 +167,8 @@
return "";
}
-
-AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
- size_t num_bytes, void* buffer,
- size_t* out_num_read) {
+std::string FsManagerAvbOps::GetPartitionPath(const char* partition) {
std::string path = "/dev/block/by-name/"s + partition;
-
- // Ensures the device path (a symlink created by init) is ready to access.
if (!WaitForFile(path, 1s)) {
LERROR << "Device path not found: " << path;
// Falls back to logical path if the physical path is not found.
@@ -182,8 +177,36 @@
// the bootloader failed to read a physical partition, it will failed to boot
// the HLOS and we won't reach the code here.
path = GetLogicalPath(partition);
- if (path.empty() || !WaitForFile(path, 1s)) return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- LINFO << "Fallback to use logical device path: " << path;
+ if (path.empty() || !WaitForFile(path, 1s)) return "";
+ }
+ return path;
+}
+
+AvbIOResult FsManagerAvbOps::GetSizeOfPartition(const char* partition,
+ uint64_t* out_size_num_byte) {
+ const auto path = GetPartitionPath(partition);
+ if (path.empty()) {
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd < 0) {
+ PERROR << "Failed to open " << path;
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ int err = ioctl(fd, BLKGETSIZE64, out_size_num_byte);
+ if (err) {
+ *out_size_num_byte = 0;
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ return AVB_IO_RESULT_OK;
+}
+
+AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
+ size_t num_bytes, void* buffer,
+ size_t* out_num_read) {
+ std::string path = GetPartitionPath(partition);
+ if (path.empty()) {
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
diff --git a/fs_mgr/libfs_avb/avb_ops.h b/fs_mgr/libfs_avb/avb_ops.h
index b39812d..12686a6 100644
--- a/fs_mgr/libfs_avb/avb_ops.h
+++ b/fs_mgr/libfs_avb/avb_ops.h
@@ -56,12 +56,14 @@
AvbIOResult ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes,
void* buffer, size_t* out_num_read);
+ AvbIOResult GetSizeOfPartition(const char* partition, uint64_t* out_size_num_byte);
AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, AvbSlotVerifyFlags flags,
std::vector<VBMetaData>* out_vbmeta_images);
private:
std::string GetLogicalPath(const std::string& partition_name);
+ std::string GetPartitionPath(const char* partition_name);
AvbOps avb_ops_;
Fstab fstab_;
};
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
index 85dbb36..90b65ce 100644
--- a/fs_mgr/libfs_avb/avb_util.cpp
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -101,7 +101,6 @@
if (wait_for_verity_dev) timeout = 1s;
std::string dev_path;
- const std::string mount_point(Basename(fstab_entry->mount_point));
const std::string device_name(GetVerityDeviceName(*fstab_entry));
android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
if (!dm.CreateDevice(device_name, table, &dev_path, timeout)) {
diff --git a/fs_mgr/libfs_avb/util.h b/fs_mgr/libfs_avb/util.h
index 427ab7c..29d1e9c 100644
--- a/fs_mgr/libfs_avb/util.h
+++ b/fs_mgr/libfs_avb/util.h
@@ -31,7 +31,7 @@
using android::base::ErrnoError;
using android::base::Result;
-#define FS_AVB_TAG "[libfs_avb]"
+#define FS_AVB_TAG "[libfs_avb] "
// Logs a message to kernel
#define LINFO LOG(INFO) << FS_AVB_TAG
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 4b81c2c..996ffd7 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -39,6 +39,7 @@
],
srcs: [
"builder.cpp",
+ "super_layout_builder.cpp",
"images.cpp",
"partition_opener.cpp",
"property_fetcher.cpp",
@@ -62,17 +63,6 @@
export_include_dirs: ["include"],
}
-filegroup {
- name: "liblp_test_srcs",
- srcs: [
- "builder_test.cpp",
- "device_test.cpp",
- "io_test.cpp",
- "test_partition_opener.cpp",
- "utility_test.cpp",
- ],
-}
-
cc_defaults {
name: "liblp_test_defaults",
defaults: ["fs_mgr_defaults"],
@@ -82,22 +72,39 @@
static_libs: [
"libcutils",
"libgmock",
- "libfs_mgr",
"liblp",
"libcrypto_static",
] + liblp_lib_deps,
header_libs: [
"libstorage_literals_headers",
],
+ target: {
+ android: {
+ srcs: [
+ "device_test.cpp",
+ "io_test.cpp",
+ ],
+ static_libs: [
+ "libfs_mgr",
+ ],
+ }
+ },
stl: "libc++_static",
- srcs: [":liblp_test_srcs"],
+ srcs: [
+ "builder_test.cpp",
+ "super_layout_builder_test.cpp",
+ "test_partition_opener.cpp",
+ "utility_test.cpp",
+ ],
}
cc_test {
name: "liblp_test",
defaults: ["liblp_test_defaults"],
- test_config: "liblp_test.xml",
test_suites: ["device-tests"],
+ auto_gen_config: true,
+ require_root: true,
+ host_supported: true
}
cc_test {
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index 0b1e522..02b64ac 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -312,6 +312,11 @@
bool ImageBuilder::AddPartitionImage(const LpMetadataPartition& partition,
const std::string& file) {
+ if (partition.num_extents == 0) {
+ LERROR << "Partition size is zero: " << GetPartitionName(partition);
+ return false;
+ }
+
// Track which extent we're processing.
uint32_t extent_index = partition.first_extent_index;
diff --git a/fs_mgr/liblp/include/liblp/super_layout_builder.h b/fs_mgr/liblp/include/liblp/super_layout_builder.h
new file mode 100644
index 0000000..d920855
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/super_layout_builder.h
@@ -0,0 +1,104 @@
+//
+// 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 <stdint.h>
+
+#include <memory>
+#include <ostream>
+#include <string>
+#include <unordered_map>
+#include <utility>
+
+#include <android-base/unique_fd.h>
+#include <liblp/builder.h>
+
+namespace android {
+namespace fs_mgr {
+
+struct SuperImageExtent {
+ enum class Type { INVALID, DATA, PARTITION, ZERO, DONTCARE };
+
+ SuperImageExtent(const SuperImageExtent& other) = default;
+ SuperImageExtent(SuperImageExtent&& other) = default;
+ SuperImageExtent(uint64_t offset, uint64_t size, Type type)
+ : offset(offset), size(size), type(type) {}
+
+ SuperImageExtent(uint64_t offset, std::shared_ptr<std::string> blob)
+ : SuperImageExtent(offset, blob->size(), Type::DATA) {
+ this->blob = blob;
+ }
+
+ SuperImageExtent(uint64_t offset, uint64_t size, const std::string& image_name,
+ uint64_t image_offset)
+ : SuperImageExtent(offset, size, Type::PARTITION) {
+ this->image_name = image_name;
+ this->image_offset = image_offset;
+ }
+
+ SuperImageExtent& operator=(const SuperImageExtent& other) = default;
+ SuperImageExtent& operator=(SuperImageExtent&& other) = default;
+
+ bool operator<(const SuperImageExtent& other) const { return offset < other.offset; }
+ bool operator==(const SuperImageExtent& other) const;
+
+ // Location, size, and type of the extent.
+ uint64_t offset = 0;
+ uint64_t size = 0;
+ Type type = Type::INVALID;
+
+ // If type == DATA, this contains the bytes to write.
+ std::shared_ptr<std::string> blob;
+ // If type == PARTITION, this contains the partition image name and
+ // offset within that file.
+ std::string image_name;
+ uint64_t image_offset = 0;
+};
+
+// The SuperLayoutBuilder allows building a sparse view of a super image. This
+// is useful for efficient flashing, eg to bypass fastbootd and directly flash
+// super without physically building and storing the image.
+class SuperLayoutBuilder final {
+ public:
+ // Open a super_empty.img, return false on failure. This must be called to
+ // initialize the tool. If it returns false, either the image failed to
+ // parse, or the tool is not compatible with how the device is configured
+ // (in which case fastbootd should be preferred).
+ [[nodiscard]] bool Open(android::base::borrowed_fd fd);
+ [[nodiscard]] bool Open(const void* data, size_t bytes);
+ [[nodiscard]] bool Open(const LpMetadata& metadata);
+
+ // Add a partition's image and size to the work list. If false is returned,
+ // there was either a duplicate partition or not enough space in super.
+ bool AddPartition(const std::string& partition_name, const std::string& image_name,
+ uint64_t partition_size);
+
+ // Return the list of extents describing the super image. If this list is
+ // empty, then there was an unrecoverable error in building the list.
+ std::vector<SuperImageExtent> GetImageLayout();
+
+ // Return the current metadata.
+ std::unique_ptr<LpMetadata> Export() const { return builder_->Export(); }
+
+ private:
+ std::unique_ptr<MetadataBuilder> builder_;
+ std::unordered_map<std::string, std::string> image_map_;
+};
+
+std::ostream& operator<<(std::ostream& stream, const SuperImageExtent& extent);
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/liblp_test.xml b/fs_mgr/liblp/liblp_test.xml
deleted file mode 100644
index 98414b1..0000000
--- a/fs_mgr/liblp/liblp_test.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Config for liblp_test">
- <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="liblp_test->/data/local/tmp/liblp_test" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="liblp_test" />
- </test>
-</configuration>
diff --git a/fs_mgr/liblp/super_layout_builder.cpp b/fs_mgr/liblp/super_layout_builder.cpp
new file mode 100644
index 0000000..37f28e1
--- /dev/null
+++ b/fs_mgr/liblp/super_layout_builder.cpp
@@ -0,0 +1,241 @@
+//
+// 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 <liblp/super_layout_builder.h>
+
+#include <liblp/liblp.h>
+
+#include "images.h"
+#include "utility.h"
+#include "writer.h"
+
+using android::base::borrowed_fd;
+using android::base::unique_fd;
+
+namespace android {
+namespace fs_mgr {
+
+bool SuperLayoutBuilder::Open(borrowed_fd fd) {
+ auto metadata = ReadFromImageFile(fd.get());
+ if (!metadata) {
+ return false;
+ }
+ return Open(*metadata.get());
+}
+
+bool SuperLayoutBuilder::Open(const void* data, size_t size) {
+ auto metadata = ReadFromImageBlob(data, size);
+ if (!metadata) {
+ return false;
+ }
+ return Open(*metadata.get());
+}
+
+bool SuperLayoutBuilder::Open(const LpMetadata& metadata) {
+ for (const auto& partition : metadata.partitions) {
+ if (partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED) {
+ // Retrofit devices are not supported.
+ return false;
+ }
+ if (!(partition.attributes & LP_PARTITION_ATTR_READONLY)) {
+ // Writable partitions are not supported.
+ return false;
+ }
+ }
+ if (!metadata.extents.empty()) {
+ // Partitions that already have extents are not supported (should
+ // never be true of super_empty.img).
+ return false;
+ }
+ if (metadata.block_devices.size() != 1) {
+ // Only one "super" is supported.
+ return false;
+ }
+
+ builder_ = MetadataBuilder::New(metadata);
+ return !!builder_;
+}
+
+bool SuperLayoutBuilder::AddPartition(const std::string& partition_name,
+ const std::string& image_name, uint64_t partition_size) {
+ auto p = builder_->FindPartition(partition_name);
+ if (!p) {
+ return false;
+ }
+ if (!builder_->ResizePartition(p, partition_size)) {
+ return false;
+ }
+ image_map_.emplace(partition_name, image_name);
+ return true;
+}
+
+// Fill the space between each extent, if any, with either a fill or dontcare
+// extent. The caller constructs a sample extent to re-use.
+static bool AddGapExtents(std::vector<SuperImageExtent>* extents, SuperImageExtent::Type gap_type) {
+ std::vector<SuperImageExtent> old = std::move(*extents);
+ std::sort(old.begin(), old.end());
+
+ *extents = {};
+
+ uint64_t current_offset = 0;
+ for (const auto& extent : old) {
+ // Check for overlapping extents - this would be a serious error.
+ if (current_offset > extent.offset) {
+ LOG(INFO) << "Overlapping extents detected; cannot layout temporary super image";
+ return false;
+ }
+
+ if (extent.offset != current_offset) {
+ uint64_t gap_size = extent.offset - current_offset;
+ extents->emplace_back(current_offset, gap_size, gap_type);
+ current_offset = extent.offset;
+ }
+
+ extents->emplace_back(extent);
+ current_offset += extent.size;
+ }
+ return true;
+}
+
+std::vector<SuperImageExtent> SuperLayoutBuilder::GetImageLayout() {
+ auto metadata = builder_->Export();
+ if (!metadata) {
+ return {};
+ }
+
+ std::vector<SuperImageExtent> extents;
+
+ // Write the primary and backup copies of geometry.
+ std::string geometry_bytes = SerializeGeometry(metadata->geometry);
+ auto blob = std::make_shared<std::string>(std::move(geometry_bytes));
+
+ extents.emplace_back(0, GetPrimaryGeometryOffset(), SuperImageExtent::Type::ZERO);
+ extents.emplace_back(GetPrimaryGeometryOffset(), blob);
+ extents.emplace_back(GetBackupGeometryOffset(), blob);
+
+ // Write the primary and backup copies of each metadata slot. When flashing,
+ // all metadata copies are the same, even for different slots.
+ std::string metadata_bytes = SerializeMetadata(*metadata.get());
+
+ // Align metadata size to 4KB. This makes the layout easily compatible with
+ // libsparse.
+ static constexpr size_t kSparseAlignment = 4096;
+ size_t metadata_aligned_bytes;
+ if (!AlignTo(metadata_bytes.size(), kSparseAlignment, &metadata_aligned_bytes)) {
+ LOG(ERROR) << "Unable to align metadata size " << metadata_bytes.size() << " to "
+ << kSparseAlignment;
+ return {};
+ }
+ metadata_bytes.resize(metadata_aligned_bytes, '\0');
+
+ // However, alignment can cause larger-than-supported metadata blocks. Fall
+ // back to fastbootd/update-super.
+ if (metadata_bytes.size() > metadata->geometry.metadata_max_size) {
+ LOG(VERBOSE) << "Aligned metadata size " << metadata_bytes.size()
+ << " is larger than maximum metadata size "
+ << metadata->geometry.metadata_max_size;
+ return {};
+ }
+
+ blob = std::make_shared<std::string>(std::move(metadata_bytes));
+ for (uint32_t i = 0; i < metadata->geometry.metadata_slot_count; i++) {
+ int64_t metadata_primary = GetPrimaryMetadataOffset(metadata->geometry, i);
+ int64_t metadata_backup = GetBackupMetadataOffset(metadata->geometry, i);
+ extents.emplace_back(metadata_primary, blob);
+ extents.emplace_back(metadata_backup, blob);
+ }
+
+ // Add extents for each partition.
+ for (const auto& partition : metadata->partitions) {
+ auto partition_name = GetPartitionName(partition);
+ auto image_name_iter = image_map_.find(partition_name);
+ if (image_name_iter == image_map_.end()) {
+ if (partition.num_extents != 0) {
+ LOG(ERROR) << "Partition " << partition_name
+ << " has extents but no image filename";
+ return {};
+ }
+ continue;
+ }
+ const auto& image_name = image_name_iter->second;
+
+ uint64_t image_offset = 0;
+ for (uint32_t i = 0; i < partition.num_extents; i++) {
+ const auto& e = metadata->extents[partition.first_extent_index + i];
+
+ if (e.target_type != LP_TARGET_TYPE_LINEAR) {
+ // Any type other than LINEAR isn't understood here. We don't even
+ // bother with ZERO, which is never generated.
+ LOG(INFO) << "Unknown extent type from liblp: " << e.target_type;
+ return {};
+ }
+
+ size_t size = e.num_sectors * LP_SECTOR_SIZE;
+ uint64_t super_offset = e.target_data * LP_SECTOR_SIZE;
+ extents.emplace_back(super_offset, size, image_name, image_offset);
+
+ image_offset += size;
+ }
+ }
+
+ if (!AddGapExtents(&extents, SuperImageExtent::Type::DONTCARE)) {
+ return {};
+ }
+ return extents;
+}
+
+bool SuperImageExtent::operator==(const SuperImageExtent& other) const {
+ if (offset != other.offset) {
+ return false;
+ }
+ if (size != other.size) {
+ return false;
+ }
+ if (type != other.type) {
+ return false;
+ }
+ switch (type) {
+ case Type::DATA:
+ return *blob == *other.blob;
+ case Type::PARTITION:
+ return image_name == other.image_name && image_offset == other.image_offset;
+ default:
+ return true;
+ }
+}
+
+std::ostream& operator<<(std::ostream& stream, const SuperImageExtent& extent) {
+ stream << "extent:" << extent.offset << ":" << extent.size << ":";
+ switch (extent.type) {
+ case SuperImageExtent::Type::DATA:
+ stream << "data";
+ break;
+ case SuperImageExtent::Type::PARTITION:
+ stream << "partition:" << extent.image_name << ":" << extent.image_offset;
+ break;
+ case SuperImageExtent::Type::ZERO:
+ stream << "zero";
+ break;
+ case SuperImageExtent::Type::DONTCARE:
+ stream << "dontcare";
+ break;
+ default:
+ stream << "invalid";
+ }
+ return stream;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/super_layout_builder_test.cpp b/fs_mgr/liblp/super_layout_builder_test.cpp
new file mode 100644
index 0000000..714b6b4
--- /dev/null
+++ b/fs_mgr/liblp/super_layout_builder_test.cpp
@@ -0,0 +1,141 @@
+//
+// 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <liblp/builder.h>
+#include <liblp/super_layout_builder.h>
+#include <storage_literals/storage_literals.h>
+
+#include "images.h"
+#include "writer.h"
+
+using namespace android::fs_mgr;
+using namespace android::storage_literals;
+
+TEST(SuperImageTool, Layout) {
+ auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* p = builder->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(p, nullptr);
+
+ auto metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ SuperLayoutBuilder tool;
+ ASSERT_TRUE(tool.Open(*metadata.get()));
+ ASSERT_TRUE(tool.AddPartition("system_a", "system.img", 16_KiB));
+
+ // Get a copy of the metadata we'd expect if flashing.
+ ASSERT_TRUE(builder->ResizePartition(p, 16_KiB));
+ metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ auto geometry_blob = std::make_shared<std::string>(SerializeGeometry(metadata->geometry));
+ auto metadata_blob = std::make_shared<std::string>(SerializeMetadata(*metadata.get()));
+ metadata_blob->resize(4_KiB, '\0');
+
+ auto extents = tool.GetImageLayout();
+ ASSERT_EQ(extents.size(), 12);
+ EXPECT_EQ(extents[0], SuperImageExtent(0, 4096, SuperImageExtent::Type::ZERO));
+ EXPECT_EQ(extents[1], SuperImageExtent(4096, geometry_blob));
+ EXPECT_EQ(extents[2], SuperImageExtent(8192, geometry_blob));
+ EXPECT_EQ(extents[3], SuperImageExtent(12288, metadata_blob));
+ EXPECT_EQ(extents[4], SuperImageExtent(16384, 4096, SuperImageExtent::Type::DONTCARE));
+ EXPECT_EQ(extents[5], SuperImageExtent(20480, metadata_blob));
+ EXPECT_EQ(extents[6], SuperImageExtent(24576, 4096, SuperImageExtent::Type::DONTCARE));
+ EXPECT_EQ(extents[7], SuperImageExtent(28672, metadata_blob));
+ EXPECT_EQ(extents[8], SuperImageExtent(32768, 4096, SuperImageExtent::Type::DONTCARE));
+ EXPECT_EQ(extents[9], SuperImageExtent(36864, metadata_blob));
+ EXPECT_EQ(extents[10], SuperImageExtent(40960, 4096, SuperImageExtent::Type::DONTCARE));
+ EXPECT_EQ(extents[11], SuperImageExtent(45056, 16384, "system.img", 0));
+}
+
+TEST(SuperImageTool, NoWritablePartitions) {
+ auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* p = builder->AddPartition("system_a", 0);
+ ASSERT_NE(p, nullptr);
+
+ auto metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ SuperLayoutBuilder tool;
+ ASSERT_FALSE(tool.Open(*metadata.get()));
+}
+
+TEST(SuperImageTool, NoRetrofit) {
+ auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* p = builder->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(p, nullptr);
+
+ auto metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ // Add an extra block device.
+ metadata->block_devices.emplace_back(metadata->block_devices[0]);
+
+ SuperLayoutBuilder tool;
+ ASSERT_FALSE(tool.Open(*metadata.get()));
+}
+
+TEST(SuperImageTool, NoRetrofit2) {
+ auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* p = builder->AddPartition(
+ "system_a", LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED);
+ ASSERT_NE(p, nullptr);
+
+ auto metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ SuperLayoutBuilder tool;
+ ASSERT_FALSE(tool.Open(*metadata.get()));
+}
+
+TEST(SuperImageTool, NoFixedPartitions) {
+ auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* p = builder->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(p, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(p, 4_KiB));
+
+ auto metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ SuperLayoutBuilder tool;
+ ASSERT_FALSE(tool.Open(*metadata.get()));
+}
+
+TEST(SuperImageTool, LargeAlignedMetadata) {
+ auto builder = MetadataBuilder::New(4_MiB, 512, 2);
+ ASSERT_NE(builder, nullptr);
+
+ auto metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+
+ SuperLayoutBuilder tool;
+ ASSERT_TRUE(tool.Open(*metadata.get()));
+
+ auto extents = tool.GetImageLayout();
+ ASSERT_TRUE(extents.empty());
+}
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index aa3a6a0..32a59a5 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -30,7 +30,7 @@
#include "liblp/liblp.h"
-#define LP_TAG "[liblp]"
+#define LP_TAG "[liblp] "
#define LWARN LOG(WARNING) << LP_TAG
#define LINFO LOG(INFO) << LP_TAG
#define LERROR LOG(ERROR) << LP_TAG
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 2165961..9d1ce7d 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -85,11 +85,9 @@
"android/snapshot/snapshot.proto",
"device_info.cpp",
"snapshot.cpp",
- "snapshot_reader.cpp",
"snapshot_stats.cpp",
"snapshot_stub.cpp",
"snapshot_metadata_updater.cpp",
- "snapshot_writer.cpp",
"partition_cow_creator.cpp",
"return.cpp",
"utility.cpp",
@@ -163,6 +161,10 @@
"libbrotli",
"libz",
"liblz4",
+ "libzstd",
+ ],
+ header_libs: [
+ "libupdate_engine_headers",
],
export_include_dirs: ["include"],
}
@@ -173,11 +175,14 @@
"libsnapshot_cow_defaults",
],
srcs: [
- "libsnapshot_cow/cow_decompress.cpp",
- "libsnapshot_cow/cow_reader.cpp",
- "libsnapshot_cow/cow_writer.cpp",
- "libsnapshot_cow/cow_format.cpp",
"libsnapshot_cow/cow_compress.cpp",
+ "libsnapshot_cow/cow_decompress.cpp",
+ "libsnapshot_cow/cow_format.cpp",
+ "libsnapshot_cow/cow_reader.cpp",
+ "libsnapshot_cow/parser_v2.cpp",
+ "libsnapshot_cow/snapshot_reader.cpp",
+ "libsnapshot_cow/writer_base.cpp",
+ "libsnapshot_cow/writer_v2.cpp",
],
host_supported: true,
recovery_available: true,
@@ -221,9 +226,7 @@
srcs: [
"partition_cow_creator_test.cpp",
"snapshot_metadata_updater_test.cpp",
- "snapshot_reader_test.cpp",
"snapshot_test.cpp",
- "snapshot_writer_test.cpp",
],
shared_libs: [
"libbinder",
@@ -252,13 +255,6 @@
header_libs: [
"libstorage_literals_headers",
],
- test_suites: [
- "vts",
- "device-tests"
- ],
- test_options: {
- min_shipping_api_level: 29,
- },
auto_gen_config: true,
require_root: true,
compile_multilib: "first",
@@ -267,17 +263,43 @@
cc_test {
name: "vts_libsnapshot_test",
defaults: ["libsnapshot_test_defaults", "libsnapshot_hal_deps"],
+ test_suites: [
+ "vts",
+ "device-tests"
+ ],
+ test_options: {
+ min_shipping_api_level: 30,
+ },
}
-sh_test {
- name: "run_snapshot_tests",
- src: "run_snapshot_tests.sh",
+cc_test {
+ name: "vab_legacy_tests",
+ defaults: ["libsnapshot_test_defaults", "libsnapshot_hal_deps"],
+ cppflags: [
+ "-DLIBSNAPSHOT_TEST_VAB_LEGACY",
+ ],
test_suites: [
- "device-tests",
+ "device-tests"
],
- required: [
- "vts_libsnapshot_test",
+ test_options: {
+ // Legacy VAB launched in Android R.
+ min_shipping_api_level: 30,
+ },
+}
+
+cc_test {
+ name: "vabc_legacy_tests",
+ defaults: ["libsnapshot_test_defaults", "libsnapshot_hal_deps"],
+ cppflags: [
+ "-DLIBSNAPSHOT_TEST_VABC_LEGACY",
],
+ test_suites: [
+ "device-tests"
+ ],
+ test_options: {
+ // Legacy VABC launched in Android S.
+ min_shipping_api_level: 31,
+ },
}
cc_test {
@@ -344,105 +366,14 @@
}
cc_test {
- name: "snapshot_power_test",
- srcs: [
- "power_test.cpp",
- ],
- static_libs: [
- "libc++fs",
- "libsnapshot",
- "update_metadata-protos",
- ],
- shared_libs: [
- "libbase",
- "libfs_mgr_binder",
- "liblog",
- ],
- gtest: false,
-}
-
-cc_defaults {
- name: "libsnapshot_fuzzer_defaults",
- defaults: [
- "libsnapshot_cow_defaults",
- ],
- native_coverage : true,
- srcs: [
- // Compile the protobuf definition again with type full.
- "android/snapshot/snapshot_fuzz.proto",
- "update_engine/update_metadata.proto",
- "fuzz_utils.cpp",
- "snapshot_fuzz.cpp",
- "snapshot_fuzz_utils.cpp",
-
- // Compile libsnapshot sources directly to avoid dependency
- // to update_metadata-protos
- ":libsnapshot_sources",
- ],
- static_libs: [
- "libbase",
- "libbrotli",
- "libc++fs",
- "libchrome",
- "libcrypto_static",
- "libcutils",
- "libext2_uuid",
- "libext4_utils",
- "libfstab",
- "libfs_mgr",
- "libgtest", // from libsnapshot_test_helpers
- "libgmock", // from libsnapshot_test_helpers
- "liblog",
- "liblp",
- "libsnapshot_cow",
- "libsnapshot_test_helpers",
- "libprotobuf-mutator",
- "libz",
- ],
- header_libs: [
- "libfiemap_headers",
- "libstorage_literals_headers",
- "libupdate_engine_headers",
- ],
- proto: {
- type: "full",
- canonical_path_from_root: false,
- local_include_dirs: ["."],
- },
-}
-
-cc_fuzz {
- name: "libsnapshot_fuzzer",
- defaults: ["libsnapshot_fuzzer_defaults"],
- corpus: ["corpus/*"],
- fuzz_config: {
- cc: ["android-virtual-ab+bugs@google.com"],
- componentid: 30545,
- hotlists: ["1646452"],
- fuzz_on_haiku_host: false,
- fuzz_on_haiku_device: true,
- },
-}
-
-cc_test {
- name: "libsnapshot_fuzzer_test",
- defaults: ["libsnapshot_fuzzer_defaults"],
- data: ["corpus/*"],
- test_suites: [
- "device-tests",
- ],
- auto_gen_config: true,
- require_root: true,
-}
-
-cc_test {
name: "cow_api_test",
defaults: [
"fs_mgr_defaults",
"libsnapshot_cow_defaults",
],
srcs: [
- "libsnapshot_cow/cow_api_test.cpp",
+ "libsnapshot_cow/snapshot_reader_test.cpp",
+ "libsnapshot_cow/test_v2.cpp",
],
cflags: [
"-D_FILE_OFFSET_BITS=64",
@@ -472,78 +403,6 @@
}
cc_binary {
- name: "make_cow_from_ab_ota",
- host_supported: true,
- device_supported: false,
- cflags: [
- "-D_FILE_OFFSET_BITS=64",
- "-Wall",
- "-Werror",
- ],
- static_libs: [
- "libbase",
- "libbspatch",
- "libbrotli",
- "libbz",
- "libchrome",
- "libcrypto",
- "libgflags",
- "liblog",
- "libprotobuf-cpp-lite",
- "libpuffpatch",
- "libsnapshot_cow",
- "libsparse",
- "libxz",
- "libz",
- "liblz4",
- "libziparchive",
- "update_metadata-protos",
- ],
- srcs: [
- "make_cow_from_ab_ota.cpp",
- ],
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
-cc_binary {
- name: "estimate_cow_from_nonab_ota",
- defaults: [
- "libsnapshot_cow_defaults",
- ],
- host_supported: true,
- device_supported: false,
- cflags: [
- "-D_FILE_OFFSET_BITS=64",
- "-Wall",
- "-Werror",
- ],
- static_libs: [
- "libbase",
- "libbrotli",
- "libbz",
- "libcrypto",
- "libgflags",
- "liblog",
- "libsnapshot_cow",
- "libsparse",
- "libz",
- "libziparchive",
- ],
- srcs: [
- "estimate_cow_from_nonab_ota.cpp",
- ],
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
-cc_binary {
name: "inspect_cow",
host_supported: true,
device_supported: true,
@@ -558,6 +417,7 @@
"libbrotli",
"libcrypto_static",
"liblog",
+ "libgflags",
"libsnapshot_cow",
"libz",
],
diff --git a/fs_mgr/libsnapshot/PowerTest.md b/fs_mgr/libsnapshot/PowerTest.md
deleted file mode 100644
index 0b0cb5d..0000000
--- a/fs_mgr/libsnapshot/PowerTest.md
+++ /dev/null
@@ -1,40 +0,0 @@
-snapshot\_power\_test
----------------------
-
-snapshot\_power\_test is a standalone test to simulate power failures during a snapshot-merge operation.
-
-### Test Setup
-
-Start by creating two large files that will be used as the pre-merge and post-merge state. You can take two different partition images (for example, a product.img from two separate builds), or just create random data:
-
- dd if=/dev/urandom of=pre-merge count=1024 bs=1048576
- dd if=/dev/urandom of=post-merge count=1024 bs=1048576
-
-Next, push these files to an unencrypted directory on the device:
-
- adb push pre-merge /data/local/unencrypted
- adb push post-merge /data/local/unencrypted
-
-Next, run the test setup:
-
- adb sync data
- adb shell /data/nativetest64/snapshot_power_test/snapshot_power_test \
- /data/local/unencrypted/pre-merge \
- /data/local/unencrypted/post-merge
-
-This will create the necessary fiemap-based images.
-
-### Running
-The actual test can be run via `run_power_test.sh`. Its syntax is:
-
- run_power_test.sh <POST_MERGE_FILE>
-
-`POST_MERGE_FILE` should be the path on the device of the image to validate the merge against. Example:
-
- run_power_test.sh /data/local/unencrypted/post-merge
-
-The device will begin the merge with a 5% chance of injecting a kernel crash every 10ms. The device should be capable of rebooting normally without user intervention. Once the merge has completed, the test will run a final check command to validate the contents of the snapshot against the post-merge file. It will error if there are any incorrect blocks.
-
-Two environment variables can be passed to `run_power_test.sh`:
-1. `FAIL_RATE` - A fraction between 0 and 100 (inclusive) indicating the probability the device should inject a kernel crash every 10ms.
-2. `DEVICE_SERIAL` - If multiple devices are attached to adb, this argument is passed as the serial to select (to `adb -s`).
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index b3763ae..fa04c43 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -108,6 +108,12 @@
// Estimated COW size from OTA manifest.
uint64 estimated_cow_size = 12;
+
+ // Enable multi-threaded compression
+ bool enable_threading = 13;
+
+ // Enable batching for COW writes
+ bool batched_writes = 14;
}
// Next: 8
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
deleted file mode 100644
index a55b42a..0000000
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (C) 2020 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.
-
-syntax = "proto3";
-package android.snapshot;
-
-import "update_engine/update_metadata.proto";
-
-// Controls the behavior of IDeviceInfo.
-// Next: 6
-message FuzzDeviceInfoData {
- bool slot_suffix_is_a = 1;
- bool is_overlayfs_setup = 2;
- bool allow_set_boot_control_merge_status = 3;
- bool allow_set_slot_as_unbootable = 4;
- bool is_recovery = 5;
-}
-
-// Controls the behavior of the test SnapshotManager.
-// Next: 2
-message FuzzSnapshotManagerData {
- bool is_local_image_manager = 1;
-}
-
-// A simplified version of CreateLogicalPartitionParams for fuzzing.
-// Next: 9
-message CreateLogicalPartitionParamsProto {
- bool use_correct_super = 1;
- string block_device = 2;
- bool has_metadata_slot = 3;
- uint32 metadata_slot = 4;
- string partition_name = 5;
- bool force_writable = 6;
- int64 timeout_millis = 7;
- string device_name = 8;
-}
-
-// Mimics the API of ISnapshotManager. Defines one action on the snapshot
-// manager.
-// Next: 18
-message SnapshotManagerActionProto {
- message NoArgs {}
- message ProcessUpdateStateArgs {
- bool has_before_cancel = 1;
- bool fail_before_cancel = 2;
- }
- message CreateLogicalAndSnapshotPartitionsArgs {
- bool use_correct_super = 1;
- string super = 2;
- int64 timeout_millis = 3;
- }
- message RecoveryCreateSnapshotDevicesArgs {
- bool has_metadata_device_object = 1;
- bool metadata_mounted = 2;
- }
- reserved 18 to 9999;
- oneof value {
- NoArgs begin_update = 1;
- NoArgs cancel_update = 2;
- bool finished_snapshot_writes = 3;
- NoArgs initiate_merge = 4;
- ProcessUpdateStateArgs process_update_state = 5;
- bool get_update_state = 6;
- chromeos_update_engine.DeltaArchiveManifest create_update_snapshots = 7;
- CreateLogicalPartitionParamsProto map_update_snapshot = 8;
- string unmap_update_snapshot = 9;
- NoArgs need_snapshots_in_first_stage_mount = 10;
- CreateLogicalAndSnapshotPartitionsArgs create_logical_and_snapshot_partitions = 11;
- bool handle_imminent_data_wipe = 12;
- NoArgs recovery_create_snapshot_devices = 13;
- RecoveryCreateSnapshotDevicesArgs recovery_create_snapshot_devices_with_metadata = 14;
- NoArgs dump = 15;
- NoArgs ensure_metadata_mounted = 16;
- NoArgs get_snapshot_merge_stats_instance = 17;
-
- // Test directives that has nothing to do with ISnapshotManager API surface.
- NoArgs switch_slot = 10000;
- }
-}
-
-// Includes all data that needs to be fuzzed.
-message SnapshotFuzzData {
- FuzzDeviceInfoData device_info_data = 1;
- FuzzSnapshotManagerData manager_data = 2;
-
- // If true:
- // - if super_data is empty, create empty super partition metadata.
- // - otherwise, create super partition metadata accordingly.
- // If false, no valid super partition metadata (it is zeroed)
- bool is_super_metadata_valid = 3;
- chromeos_update_engine.DeltaArchiveManifest super_data = 4;
-
- // Whether the directory that mocks /metadata/ota/snapshot is created.
- bool has_metadata_snapshots_dir = 5;
-
- // More data used to prep the test before running actions.
- reserved 6 to 9999;
- repeated SnapshotManagerActionProto actions = 10000;
-}
diff --git a/fs_mgr/libsnapshot/corpus/avoid-io-in-fuzzer.txt b/fs_mgr/libsnapshot/corpus/avoid-io-in-fuzzer.txt
deleted file mode 100644
index c474f4c..0000000
--- a/fs_mgr/libsnapshot/corpus/avoid-io-in-fuzzer.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-device_info_data {
- allow_set_slot_as_unbootable: true
- is_recovery: true
-}
-is_super_metadata_valid: true
-super_data {
- partitions {
- partition_name: "sys_a"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "vnnd_"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "prd_a"
- new_partition_info {
- }
- }
- dynamic_partition_metadata {
- groups {
- name: "group_google_dp_a"
- size: 34375467008
- partition_names: "sys_a"
- partition_names: "vnd_a"
- partition_names: "prd_a"
- }
- }
-}
-has_metadata_snapshots_dir: true
-actions {
- handle_imminent_data_wipe: true
-}
-actions {
- begin_update {
- }
-}
diff --git a/fs_mgr/libsnapshot/corpus/launch_device.txt b/fs_mgr/libsnapshot/corpus/launch_device.txt
deleted file mode 100644
index 55a7f2c..0000000
--- a/fs_mgr/libsnapshot/corpus/launch_device.txt
+++ /dev/null
@@ -1,161 +0,0 @@
-device_info_data {
- slot_suffix_is_a: true
- is_overlayfs_setup: false
- allow_set_boot_control_merge_status: true
- allow_set_slot_as_unbootable: true
- is_recovery: false
-}
-manager_data {
- is_local_image_manager: false
-}
-is_super_metadata_valid: true
-super_data {
- partitions {
- partition_name: "sys_a"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "vnd_a"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "prd_a"
- new_partition_info {
- size: 3145728
- }
- }
- dynamic_partition_metadata {
- groups {
- name: "group_google_dp_a"
- size: 15728640
- partition_names: "sys_a"
- partition_names: "vnd_a"
- partition_names: "prd_a"
- }
- }
-}
-has_metadata_snapshots_dir: true
-actions {
- begin_update {
- }
-}
-actions {
- create_update_snapshots {
- partitions {
- partition_name: "sys"
- new_partition_info {
- size: 3878912
- }
- operations {
- type: ZERO,
- dst_extents {
- start_block: 0
- num_blocks: 947
- }
- }
- }
- partitions {
- partition_name: "vnd"
- new_partition_info {
- size: 3878912
- }
- operations {
- type: ZERO,
- dst_extents {
- start_block: 0
- num_blocks: 947
- }
- }
- }
- partitions {
- partition_name: "prd"
- new_partition_info {
- size: 3878912
- }
- operations {
- type: ZERO,
- dst_extents {
- start_block: 0
- num_blocks: 947
- }
- }
- }
- dynamic_partition_metadata {
- groups {
- name: "group_google_dp"
- size: 15728640
- partition_names: "sys"
- partition_names: "vnd"
- partition_names: "prd"
- }
- }
- }
-}
-actions {
- map_update_snapshot {
- use_correct_super: true
- has_metadata_slot: true
- metadata_slot: 1
- partition_name: "sys_b"
- force_writable: true
- timeout_millis: 3000
- }
-}
-actions {
- map_update_snapshot {
- use_correct_super: true
- has_metadata_slot: true
- metadata_slot: 1
- partition_name: "vnd_b"
- force_writable: true
- timeout_millis: 3000
- }
-}
-actions {
- map_update_snapshot {
- use_correct_super: true
- has_metadata_slot: true
- metadata_slot: 1
- partition_name: "prd_b"
- force_writable: true
- timeout_millis: 3000
- }
-}
-actions {
- finished_snapshot_writes: false
-}
-actions {
- unmap_update_snapshot: "sys_b"
-}
-actions {
- unmap_update_snapshot: "vnd_b"
-}
-actions {
- unmap_update_snapshot: "prd_b"
-}
-actions {
- switch_slot {
- }
-}
-actions {
- need_snapshots_in_first_stage_mount {
- }
-}
-actions {
- create_logical_and_snapshot_partitions {
- use_correct_super: true
- timeout_millis: 5000
- }
-}
-actions {
- initiate_merge {
- }
-}
-actions {
- process_update_state {
- }
-}
diff --git a/fs_mgr/libsnapshot/estimate_cow_from_nonab_ota.cpp b/fs_mgr/libsnapshot/estimate_cow_from_nonab_ota.cpp
deleted file mode 100644
index 45833e1..0000000
--- a/fs_mgr/libsnapshot/estimate_cow_from_nonab_ota.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-//
-// Copyright (C) 2020 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 <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <gflags/gflags.h>
-#include <libsnapshot/cow_writer.h>
-#include <openssl/sha.h>
-#include <sparse/sparse.h>
-#include <ziparchive/zip_archive.h>
-
-DEFINE_string(source_tf, "", "Source target files (dir or zip file)");
-DEFINE_string(ota_tf, "", "Target files of the build for an OTA");
-DEFINE_string(compression, "gz", "Compression (options: none, gz, brotli)");
-
-namespace android {
-namespace snapshot {
-
-using android::base::borrowed_fd;
-using android::base::unique_fd;
-
-static constexpr size_t kBlockSize = 4096;
-
-void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
- unsigned int, const char* message) {
- if (severity == android::base::ERROR) {
- fprintf(stderr, "%s\n", message);
- } else {
- fprintf(stdout, "%s\n", message);
- }
-}
-
-class TargetFilesPackage final {
- public:
- explicit TargetFilesPackage(const std::string& path);
-
- bool Open();
- bool HasFile(const std::string& path);
- std::unordered_set<std::string> GetDynamicPartitionNames();
- unique_fd OpenFile(const std::string& path);
- unique_fd OpenImage(const std::string& path);
-
- private:
- std::string path_;
- unique_fd fd_;
- std::unique_ptr<ZipArchive, decltype(&CloseArchive)> zip_;
-};
-
-TargetFilesPackage::TargetFilesPackage(const std::string& path)
- : path_(path), zip_(nullptr, &CloseArchive) {}
-
-bool TargetFilesPackage::Open() {
- fd_.reset(open(path_.c_str(), O_RDONLY));
- if (fd_ < 0) {
- PLOG(ERROR) << "open failed: " << path_;
- return false;
- }
-
- struct stat s;
- if (fstat(fd_.get(), &s) < 0) {
- PLOG(ERROR) << "fstat failed: " << path_;
- return false;
- }
- if (S_ISDIR(s.st_mode)) {
- return true;
- }
-
- // Otherwise, assume it's a zip file.
- ZipArchiveHandle handle;
- if (OpenArchiveFd(fd_.get(), path_.c_str(), &handle, false)) {
- LOG(ERROR) << "Could not open " << path_ << " as a zip archive.";
- return false;
- }
- zip_.reset(handle);
- return true;
-}
-
-bool TargetFilesPackage::HasFile(const std::string& path) {
- if (zip_) {
- ZipEntry64 entry;
- return !FindEntry(zip_.get(), path, &entry);
- }
-
- auto full_path = path_ + "/" + path;
- return access(full_path.c_str(), F_OK) == 0;
-}
-
-unique_fd TargetFilesPackage::OpenFile(const std::string& path) {
- if (!zip_) {
- auto full_path = path_ + "/" + path;
- unique_fd fd(open(full_path.c_str(), O_RDONLY));
- if (fd < 0) {
- PLOG(ERROR) << "open failed: " << full_path;
- return {};
- }
- return fd;
- }
-
- ZipEntry64 entry;
- if (FindEntry(zip_.get(), path, &entry)) {
- LOG(ERROR) << path << " not found in archive: " << path_;
- return {};
- }
-
- TemporaryFile temp;
- if (temp.fd < 0) {
- PLOG(ERROR) << "mkstemp failed";
- return {};
- }
-
- LOG(INFO) << "Extracting " << path << " from " << path_ << " ...";
- if (ExtractEntryToFile(zip_.get(), &entry, temp.fd)) {
- LOG(ERROR) << "could not extract " << path << " from " << path_;
- return {};
- }
- if (lseek(temp.fd, 0, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed";
- return {};
- }
- return unique_fd{temp.release()};
-}
-
-unique_fd TargetFilesPackage::OpenImage(const std::string& path) {
- auto fd = OpenFile(path);
- if (fd < 0) {
- return {};
- }
-
- LOG(INFO) << "Unsparsing " << path << " ...";
- std::unique_ptr<struct sparse_file, decltype(&sparse_file_destroy)> s(
- sparse_file_import(fd.get(), false, false), &sparse_file_destroy);
- if (!s) {
- return fd;
- }
-
- TemporaryFile temp;
- if (temp.fd < 0) {
- PLOG(ERROR) << "mkstemp failed";
- return {};
- }
- if (sparse_file_write(s.get(), temp.fd, false, false, false) < 0) {
- LOG(ERROR) << "sparse_file_write failed";
- return {};
- }
- if (lseek(temp.fd, 0, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed";
- return {};
- }
-
- fd.reset(temp.release());
- return fd;
-}
-
-std::unordered_set<std::string> TargetFilesPackage::GetDynamicPartitionNames() {
- auto fd = OpenFile("META/misc_info.txt");
- if (fd < 0) {
- return {};
- }
-
- std::string contents;
- if (!android::base::ReadFdToString(fd, &contents)) {
- PLOG(ERROR) << "read failed";
- return {};
- }
-
- std::unordered_set<std::string> set;
-
- auto lines = android::base::Split(contents, "\n");
- for (const auto& line : lines) {
- auto parts = android::base::Split(line, "=");
- if (parts.size() == 2 && parts[0] == "dynamic_partition_list") {
- auto partitions = android::base::Split(parts[1], " ");
- for (const auto& name : partitions) {
- if (!name.empty()) {
- set.emplace(name);
- }
- }
- break;
- }
- }
- return set;
-}
-
-class NonAbEstimator final {
- public:
- NonAbEstimator(const std::string& ota_tf_path, const std::string& source_tf_path)
- : ota_tf_path_(ota_tf_path), source_tf_path_(source_tf_path) {}
-
- bool Run();
-
- private:
- bool OpenPackages();
- bool AnalyzePartition(const std::string& partition_name);
- std::unordered_map<std::string, uint64_t> GetBlockMap(borrowed_fd fd);
-
- std::string ota_tf_path_;
- std::string source_tf_path_;
- std::unique_ptr<TargetFilesPackage> ota_tf_;
- std::unique_ptr<TargetFilesPackage> source_tf_;
- uint64_t size_ = 0;
-};
-
-bool NonAbEstimator::Run() {
- if (!OpenPackages()) {
- return false;
- }
-
- auto partitions = ota_tf_->GetDynamicPartitionNames();
- if (partitions.empty()) {
- LOG(ERROR) << "No dynamic partitions found in META/misc_info.txt";
- return false;
- }
- for (const auto& partition : partitions) {
- if (!AnalyzePartition(partition)) {
- return false;
- }
- }
-
- int64_t size_in_mb = int64_t(double(size_) / 1024.0 / 1024.0);
-
- std::cout << "Estimated COW size: " << size_ << " (" << size_in_mb << "MiB)\n";
- return true;
-}
-
-bool NonAbEstimator::OpenPackages() {
- ota_tf_ = std::make_unique<TargetFilesPackage>(ota_tf_path_);
- if (!ota_tf_->Open()) {
- return false;
- }
- if (!source_tf_path_.empty()) {
- source_tf_ = std::make_unique<TargetFilesPackage>(source_tf_path_);
- if (!source_tf_->Open()) {
- return false;
- }
- }
- return true;
-}
-
-static std::string SHA256(const std::string& input) {
- std::string hash(32, '\0');
- SHA256_CTX c;
- SHA256_Init(&c);
- SHA256_Update(&c, input.data(), input.size());
- SHA256_Final(reinterpret_cast<unsigned char*>(hash.data()), &c);
- return hash;
-}
-
-bool NonAbEstimator::AnalyzePartition(const std::string& partition_name) {
- auto path = "IMAGES/" + partition_name + ".img";
- auto fd = ota_tf_->OpenImage(path);
- if (fd < 0) {
- return false;
- }
-
- unique_fd source_fd;
- uint64_t source_size = 0;
- std::unordered_map<std::string, uint64_t> source_blocks;
- if (source_tf_) {
- auto dap = source_tf_->GetDynamicPartitionNames();
-
- source_fd = source_tf_->OpenImage(path);
- if (source_fd >= 0) {
- struct stat s;
- if (fstat(source_fd.get(), &s)) {
- PLOG(ERROR) << "fstat failed";
- return false;
- }
- source_size = s.st_size;
-
- std::cout << "Hashing blocks for " << partition_name << "...\n";
- source_blocks = GetBlockMap(source_fd);
- if (source_blocks.empty()) {
- LOG(ERROR) << "Could not build a block map for source partition: "
- << partition_name;
- return false;
- }
- } else {
- if (dap.count(partition_name)) {
- return false;
- }
- LOG(ERROR) << "Warning: " << partition_name
- << " has no incremental diff since it's not in the source image.";
- }
- }
-
- TemporaryFile cow;
- if (cow.fd < 0) {
- PLOG(ERROR) << "mkstemp failed";
- return false;
- }
-
- CowOptions options;
- options.block_size = kBlockSize;
- options.compression = FLAGS_compression;
-
- auto writer = std::make_unique<CowWriter>(options);
- if (!writer->Initialize(borrowed_fd{cow.fd})) {
- LOG(ERROR) << "Could not initialize COW writer";
- return false;
- }
-
- LOG(INFO) << "Analyzing " << partition_name << " ...";
-
- std::string zeroes(kBlockSize, '\0');
- std::string chunk(kBlockSize, '\0');
- std::string src_chunk(kBlockSize, '\0');
- uint64_t next_block_number = 0;
- while (true) {
- if (!android::base::ReadFully(fd, chunk.data(), chunk.size())) {
- if (errno) {
- PLOG(ERROR) << "read failed";
- return false;
- }
- break;
- }
-
- uint64_t block_number = next_block_number++;
- if (chunk == zeroes) {
- if (!writer->AddZeroBlocks(block_number, 1)) {
- LOG(ERROR) << "Could not add zero block";
- return false;
- }
- continue;
- }
-
- uint64_t source_offset = block_number * kBlockSize;
- if (source_fd >= 0 && source_offset <= source_size) {
- off64_t offset = block_number * kBlockSize;
- if (android::base::ReadFullyAtOffset(source_fd, src_chunk.data(), src_chunk.size(),
- offset)) {
- if (chunk == src_chunk) {
- continue;
- }
- } else if (errno) {
- PLOG(ERROR) << "pread failed";
- return false;
- }
- }
-
- auto hash = SHA256(chunk);
- if (auto iter = source_blocks.find(hash); iter != source_blocks.end()) {
- if (!writer->AddCopy(block_number, iter->second)) {
- return false;
- }
- continue;
- }
-
- if (!writer->AddRawBlocks(block_number, chunk.data(), chunk.size())) {
- return false;
- }
- }
-
- if (!writer->Finalize()) {
- return false;
- }
-
- struct stat s;
- if (fstat(cow.fd, &s) < 0) {
- PLOG(ERROR) << "fstat failed";
- return false;
- }
-
- size_ += s.st_size;
- return true;
-}
-
-std::unordered_map<std::string, uint64_t> NonAbEstimator::GetBlockMap(borrowed_fd fd) {
- std::string chunk(kBlockSize, '\0');
-
- std::unordered_map<std::string, uint64_t> block_map;
- uint64_t block_number = 0;
- while (true) {
- if (!android::base::ReadFully(fd, chunk.data(), chunk.size())) {
- if (errno) {
- PLOG(ERROR) << "read failed";
- return {};
- }
- break;
- }
- auto hash = SHA256(chunk);
- block_map[hash] = block_number;
- block_number++;
- }
- return block_map;
-}
-
-} // namespace snapshot
-} // namespace android
-
-using namespace android::snapshot;
-
-int main(int argc, char** argv) {
- android::base::InitLogging(argv, android::snapshot::MyLogger);
- gflags::SetUsageMessage("Estimate VAB disk usage from Non A/B builds");
- gflags::ParseCommandLineFlags(&argc, &argv, false);
-
- if (FLAGS_ota_tf.empty()) {
- std::cerr << "Must specify -ota_tf on the command-line." << std::endl;
- return 1;
- }
-
- NonAbEstimator estimator(FLAGS_ota_tf, FLAGS_source_tf);
- if (!estimator.Run()) {
- return 1;
- }
- return 0;
-}
diff --git a/fs_mgr/libsnapshot/fuzz.sh b/fs_mgr/libsnapshot/fuzz.sh
deleted file mode 100755
index 5995cef..0000000
--- a/fs_mgr/libsnapshot/fuzz.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/bash
-PROJECT_PATH=system/core/fs_mgr/libsnapshot
-FUZZ_TARGET=libsnapshot_fuzzer
-TARGET_ARCH=$(get_build_var TARGET_ARCH)
-FUZZ_BINARY=/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/${FUZZ_TARGET}
-DEVICE_INIT_CORPUS_DIR=/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/corpus
-DEVICE_GENERATED_CORPUS_DIR=/data/local/tmp/${FUZZ_TARGET}/corpus
-DEVICE_GCOV_DIR=/data/local/tmp/${FUZZ_TARGET}/gcov
-HOST_SCRATCH_DIR=/tmp/${FUZZ_TARGET}
-GCOV_TOOL=${HOST_SCRATCH_DIR}/llvm-gcov
-
-build_normal() (
- pushd $(gettop)
- NATIVE_COVERAGE="" NATIVE_LINE_COVERAGE="" NATIVE_COVERAGE_PATHS="" m ${FUZZ_TARGET}
- ret=$?
- popd
- return ${ret}
-)
-
-build_cov() {
- pushd $(gettop)
- NATIVE_COVERAGE="true" NATIVE_LINE_COVERAGE="true" NATIVE_COVERAGE_PATHS="${PROJECT_PATH}" m ${FUZZ_TARGET}
- ret=$?
- popd
- return ${ret}
-}
-
-prepare_device() {
- adb root && adb remount &&
- adb shell mkdir -p ${DEVICE_GENERATED_CORPUS_DIR} &&
- adb shell rm -rf ${DEVICE_GCOV_DIR} &&
- adb shell mkdir -p ${DEVICE_GCOV_DIR}
-}
-
-push_binary() {
- adb push ${ANDROID_PRODUCT_OUT}/${FUZZ_BINARY} ${FUZZ_BINARY} &&
- adb push ${ANDROID_PRODUCT_OUT}/${DEVICE_INIT_CORPUS_DIR} $(dirname ${FUZZ_BINARY})
-}
-
-prepare_host() {
- which lcov || {
- echo "please run:";
- echo " sudo apt-get install lcov ";
- return 1;
- }
- rm -rf ${HOST_SCRATCH_DIR} &&
- mkdir -p ${HOST_SCRATCH_DIR}
-}
-
-# run_snapshot_fuzz -runs=10000
-generate_corpus() {
- [[ "$@" ]] || { echo "run with -runs=X"; return 1; }
-
- prepare_device &&
- build_normal &&
- push_binary &&
- adb shell ${FUZZ_BINARY} "$@" ${DEVICE_INIT_CORPUS_DIR} ${DEVICE_GENERATED_CORPUS_DIR}
-}
-
-run_snapshot_fuzz() {
- prepare_device &&
- build_cov &&
- push_binary &&
- adb shell GCOV_PREFIX=${DEVICE_GCOV_DIR} GCOV_PREFIX_STRIP=3 \
- ${FUZZ_BINARY} \
- -runs=0 \
- ${DEVICE_INIT_CORPUS_DIR} ${DEVICE_GENERATED_CORPUS_DIR}
-}
-
-show_fuzz_result() {
- prepare_host &&
- unzip -o -j -d ${HOST_SCRATCH_DIR} ${ANDROID_PRODUCT_OUT}/coverage/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/${FUZZ_TARGET}.zip &&
- adb shell find ${DEVICE_GCOV_DIR} -type f | xargs -I {} adb pull {} ${HOST_SCRATCH_DIR} &&
- ls ${HOST_SCRATCH_DIR} &&
- cat > ${GCOV_TOOL} <<< '
-#!/bin/bash
-exec llvm-cov gcov "$@"
-' &&
- chmod +x ${GCOV_TOOL} &&
- lcov --directory ${HOST_SCRATCH_DIR} --base-directory $(gettop) --gcov-tool ${GCOV_TOOL} --capture -o ${HOST_SCRATCH_DIR}/report.cov &&
- genhtml ${HOST_SCRATCH_DIR}/report.cov -o ${HOST_SCRATCH_DIR}/html &&
- echo file://$(realpath ${HOST_SCRATCH_DIR}/html/index.html)
-}
-
-# run_snapshot_fuzz -runs=10000
-run_snapshot_fuzz_all() {
- generate_corpus "$@" &&
- run_snapshot_fuzz &&
- show_fuzz_result
-}
diff --git a/fs_mgr/libsnapshot/fuzz_utils.cpp b/fs_mgr/libsnapshot/fuzz_utils.cpp
deleted file mode 100644
index 0263f7e..0000000
--- a/fs_mgr/libsnapshot/fuzz_utils.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2020 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 "fuzz_utils.h"
-
-#include <android-base/logging.h>
-
-namespace android::fuzz {
-
-void CheckInternal(bool value, std::string_view msg) {
- CHECK(value) << msg;
-}
-
-const google::protobuf::OneofDescriptor* GetProtoValueDescriptor(
- const google::protobuf::Descriptor* action_desc) {
- CHECK(action_desc);
- CHECK(action_desc->oneof_decl_count() == 1)
- << action_desc->oneof_decl_count() << " oneof fields found in " << action_desc->name()
- << "; only one is expected.";
- auto* oneof_value_desc = action_desc->oneof_decl(0);
- CHECK(oneof_value_desc);
- CHECK(oneof_value_desc->name() == "value")
- << "oneof field has name " << oneof_value_desc->name();
- return oneof_value_desc;
-}
-
-} // namespace android::fuzz
diff --git a/fs_mgr/libsnapshot/fuzz_utils.h b/fs_mgr/libsnapshot/fuzz_utils.h
deleted file mode 100644
index 20b13b2..0000000
--- a/fs_mgr/libsnapshot/fuzz_utils.h
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright (C) 2020 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 <map>
-#include <string>
-#include <string_view>
-
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>
-
-// Utilities for using a protobuf definition to fuzz APIs in a class.
-// Terms:
-// The "fuzzed class" is the C++ class definition whose functions are fuzzed.
-// The "fuzzed object" is an instantiated object of the fuzzed class. It is
-// typically created and destroyed for each test run.
-// An "action" is an operation on the fuzzed object that may mutate its state.
-// This typically involves one function call into the fuzzed object.
-
-namespace android::fuzz {
-
-// CHECK(value) << msg
-void CheckInternal(bool value, std::string_view msg);
-
-// Get the oneof descriptor inside Action
-const google::protobuf::OneofDescriptor* GetProtoValueDescriptor(
- const google::protobuf::Descriptor* action_desc);
-
-template <typename Class>
-using FunctionMapImpl =
- std::map<int, std::function<void(Class*, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc)>>;
-
-template <typename Class>
-class FunctionMap : public FunctionMapImpl<Class> {
- public:
- void CheckEmplace(typename FunctionMapImpl<Class>::key_type key,
- typename FunctionMapImpl<Class>::mapped_type&& value) {
- auto [it, inserted] = this->emplace(key, std::move(value));
- CheckInternal(inserted,
- "Multiple implementation registered for tag number " + std::to_string(key));
- }
-};
-
-template <typename Action>
-int CheckConsistency() {
- const auto* function_map = Action::GetFunctionMap();
- const auto* action_value_desc = GetProtoValueDescriptor(Action::Proto::GetDescriptor());
-
- for (int field_index = 0; field_index < action_value_desc->field_count(); ++field_index) {
- const auto* field_desc = action_value_desc->field(field_index);
- CheckInternal(function_map->find(field_desc->number()) != function_map->end(),
- "Missing impl for function " + field_desc->camelcase_name());
- }
- return 0;
-}
-
-// Get the field descriptor for the oneof field in the action message. If no oneof field is set,
-// return nullptr.
-template <typename Action>
-const google::protobuf::FieldDescriptor* GetValueFieldDescriptor(
- const typename Action::Proto& action_proto) {
- static auto* action_value_desc = GetProtoValueDescriptor(Action::Proto::GetDescriptor());
-
- auto* action_refl = Action::Proto::GetReflection();
- if (!action_refl->HasOneof(action_proto, action_value_desc)) {
- return nullptr;
- }
- return action_refl->GetOneofFieldDescriptor(action_proto, action_value_desc);
-}
-
-template <typename Action>
-void ExecuteActionProto(typename Action::ClassType* module,
- const typename Action::Proto& action_proto) {
- const auto* field_desc = GetValueFieldDescriptor<Action>(action_proto);
- if (field_desc == nullptr) return;
- auto number = field_desc->number();
- const auto& map = *Action::GetFunctionMap();
- auto it = map.find(number);
- CheckInternal(it != map.end(), "Missing impl for function " + field_desc->camelcase_name());
- const auto& func = it->second;
- func(module, action_proto, field_desc);
-}
-
-template <typename Action>
-void ExecuteAllActionProtos(
- typename Action::ClassType* module,
- const google::protobuf::RepeatedPtrField<typename Action::Proto>& action_protos) {
- for (const auto& proto : action_protos) {
- ExecuteActionProto<Action>(module, proto);
- }
-}
-
-// Safely cast message to T. Returns a pointer to message if cast successfully, otherwise nullptr.
-template <typename T>
-const T* SafeCast(const google::protobuf::Message& message) {
- if (message.GetDescriptor() != T::GetDescriptor()) {
- return nullptr;
- }
- return static_cast<const T*>(&message);
-}
-
-// Cast message to const T&. Abort if type mismatch.
-template <typename T>
-const T& CheckedCast(const google::protobuf::Message& message) {
- const auto* ptr = SafeCast<T>(message);
- CheckInternal(ptr, "Cannot cast " + message.GetDescriptor()->name() + " to " +
- T::GetDescriptor()->name());
- return *ptr;
-}
-
-// A templated way to a primitive field from a message using reflection.
-template <typename T>
-struct PrimitiveGetter;
-#define FUZZ_DEFINE_PRIMITIVE_GETTER(type, func_name) \
- template <> \
- struct PrimitiveGetter<type> { \
- static constexpr const auto fp = &google::protobuf::Reflection::func_name; \
- }
-
-FUZZ_DEFINE_PRIMITIVE_GETTER(bool, GetBool);
-FUZZ_DEFINE_PRIMITIVE_GETTER(uint32_t, GetUInt32);
-FUZZ_DEFINE_PRIMITIVE_GETTER(int32_t, GetInt32);
-FUZZ_DEFINE_PRIMITIVE_GETTER(uint64_t, GetUInt64);
-FUZZ_DEFINE_PRIMITIVE_GETTER(int64_t, GetInt64);
-FUZZ_DEFINE_PRIMITIVE_GETTER(double, GetDouble);
-FUZZ_DEFINE_PRIMITIVE_GETTER(float, GetFloat);
-
-// ActionPerformer extracts arguments from the protobuf message, and then call FuzzFunction
-// with these arguments.
-template <typename FuzzFunction, typename Signature, typename Enabled = void>
-struct ActionPerformerImpl; // undefined
-
-template <typename FuzzFunction, typename MessageProto>
-struct ActionPerformerImpl<
- FuzzFunction, void(const MessageProto&),
- typename std::enable_if_t<std::is_base_of_v<google::protobuf::Message, MessageProto>>> {
- static typename FuzzFunction::ReturnType Invoke(
- typename FuzzFunction::ClassType* module, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc) {
- const MessageProto& arg = CheckedCast<std::remove_reference_t<MessageProto>>(
- action_proto.GetReflection()->GetMessage(action_proto, field_desc));
- return FuzzFunction::ImplBody(module, arg);
- }
-};
-
-template <typename FuzzFunction, typename Primitive>
-struct ActionPerformerImpl<FuzzFunction, void(Primitive),
- typename std::enable_if_t<std::is_arithmetic_v<Primitive>>> {
- static typename FuzzFunction::ReturnType Invoke(
- typename FuzzFunction::ClassType* module, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc) {
- Primitive arg = std::invoke(PrimitiveGetter<Primitive>::fp, action_proto.GetReflection(),
- action_proto, field_desc);
- return FuzzFunction::ImplBody(module, arg);
- }
-};
-
-template <typename FuzzFunction>
-struct ActionPerformerImpl<FuzzFunction, void()> {
- static typename FuzzFunction::ReturnType Invoke(typename FuzzFunction::ClassType* module,
- const google::protobuf::Message&,
- const google::protobuf::FieldDescriptor*) {
- return FuzzFunction::ImplBody(module);
- }
-};
-
-template <typename FuzzFunction>
-struct ActionPerformerImpl<FuzzFunction, void(const std::string&)> {
- static typename FuzzFunction::ReturnType Invoke(
- typename FuzzFunction::ClassType* module, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc) {
- std::string scratch;
- const std::string& arg = action_proto.GetReflection()->GetStringReference(
- action_proto, field_desc, &scratch);
- return FuzzFunction::ImplBody(module, arg);
- }
-};
-
-template <typename FuzzFunction>
-struct ActionPerformer : ActionPerformerImpl<FuzzFunction, typename FuzzFunction::Signature> {};
-
-} // namespace android::fuzz
-
-// Fuzz existing C++ class, ClassType, with a collection of functions under the name Action.
-//
-// Prerequisite: ActionProto must be defined in Protobuf to describe possible actions:
-// message FooActionProto {
-// message NoArgs {}
-// oneof value {
-// bool do_foo = 1;
-// NoArgs do_bar = 1;
-// }
-// }
-// Use it to fuzz a C++ class Foo by doing the following:
-// FUZZ_CLASS(Foo, FooAction)
-// After linking functions of Foo to FooAction, execute all actions by:
-// FooAction::ExecuteAll(foo_object, action_protos)
-#define FUZZ_CLASS(Class, Action) \
- class Action { \
- public: \
- using Proto = Action##Proto; \
- using ClassType = Class; \
- using FunctionMap = android::fuzz::FunctionMap<Class>; \
- static FunctionMap* GetFunctionMap() { \
- static Action::FunctionMap map; \
- return ↦ \
- } \
- static void ExecuteAll(Class* module, \
- const google::protobuf::RepeatedPtrField<Proto>& action_protos) { \
- [[maybe_unused]] static int consistent = android::fuzz::CheckConsistency<Action>(); \
- android::fuzz::ExecuteAllActionProtos<Action>(module, action_protos); \
- } \
- }
-
-#define FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName) Action##_##FunctionName
-#define FUZZ_FUNCTION_TAG_NAME(FunctionName) k##FunctionName
-
-// Implement an action defined in protobuf. Example:
-// message FooActionProto {
-// oneof value {
-// bool do_foo = 1;
-// }
-// }
-// class Foo { public: void DoAwesomeFoo(bool arg); };
-// FUZZ_OBJECT(FooAction, Foo);
-// FUZZ_FUNCTION(FooAction, DoFoo, void, IFoo* module, bool arg) {
-// module->DoAwesomeFoo(arg);
-// }
-// The name DoFoo is the camel case name of the action in protobuf definition of FooActionProto.
-#define FUZZ_FUNCTION(Action, FunctionName, Return, ModuleArg, ...) \
- class FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName) { \
- public: \
- using ActionType = Action; \
- using ClassType = Action::ClassType; \
- using ReturnType = Return; \
- using Signature = void(__VA_ARGS__); \
- static constexpr const char name[] = #FunctionName; \
- static constexpr const auto tag = \
- Action::Proto::ValueCase::FUZZ_FUNCTION_TAG_NAME(FunctionName); \
- static ReturnType ImplBody(ModuleArg, ##__VA_ARGS__); \
- \
- private: \
- static bool registered_; \
- }; \
- auto FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName)::registered_ = ([] { \
- auto tag = FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName)::tag; \
- auto func = &::android::fuzz::ActionPerformer<FUZZ_FUNCTION_CLASS_NAME( \
- Action, FunctionName)>::Invoke; \
- Action::GetFunctionMap()->CheckEmplace(tag, func); \
- return true; \
- })(); \
- Return FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName)::ImplBody(ModuleArg, ##__VA_ARGS__)
-
-// Implement a simple action by linking it to the function with the same name. Example:
-// message FooActionProto {
-// message NoArgs {}
-// oneof value {
-// NoArgs do_bar = 1;
-// }
-// }
-// class Foo { public void DoBar(); };
-// FUZZ_OBJECT(FooAction, Foo);
-// FUZZ_FUNCTION(FooAction, DoBar);
-// The name DoBar is the camel case name of the action in protobuf definition of FooActionProto, and
-// also the name of the function of Foo.
-#define FUZZ_SIMPLE_FUNCTION(Action, FunctionName) \
- FUZZ_FUNCTION(Action, FunctionName, \
- decltype(std::declval<Action::ClassType>().FunctionName()), \
- Action::ClassType* module) { \
- return module->FunctionName(); \
- }
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index ba75a8d..3a81f63 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -15,7 +15,9 @@
#pragma once
#include <stdint.h>
-#include <string>
+
+#include <optional>
+#include <string_view>
namespace android {
namespace snapshot {
@@ -26,8 +28,12 @@
static constexpr uint32_t kCowVersionManifest = 2;
-static constexpr size_t BLOCK_SZ = 4096;
-static constexpr size_t BLOCK_SHIFT = (__builtin_ffs(BLOCK_SZ) - 1);
+static constexpr uint32_t kMinCowVersion = 1;
+static constexpr uint32_t kMaxCowVersion = 2;
+
+// Normally, this should be kMaxCowVersion. When a new version is under testing
+// it may be the previous value of kMaxCowVersion.
+static constexpr uint32_t kDefaultCowVersion = 2;
// This header appears as the first sequence of bytes in the COW. All fields
// in the layout are little-endian encoded. The on-disk layout is:
@@ -53,13 +59,15 @@
// between writing the last operation/data pair, or the footer itself. In this
// case, the safest way to proceed is to assume the last operation is faulty.
-struct CowHeader {
+struct CowHeaderPrefix {
uint64_t magic;
uint16_t major_version;
uint16_t minor_version;
+ uint16_t header_size; // size of CowHeader.
+} __attribute__((packed));
- // Size of this struct.
- uint16_t header_size;
+struct CowHeader {
+ CowHeaderPrefix prefix;
// Size of footer struct
uint16_t footer_size;
@@ -89,7 +97,7 @@
// the compression type of that data (see constants below).
uint8_t compression;
- // Length of Footer Data. Currently 64 for both checksums
+ // Length of Footer Data. Currently 64.
uint16_t data_length;
// The amount of file space used by Cow operations
@@ -99,14 +107,6 @@
uint64_t num_ops;
} __attribute__((packed));
-struct CowFooterData {
- // SHA256 checksums of Footer op
- uint8_t footer_checksum[32];
-
- // SHA256 of the operation sequence.
- uint8_t ops_checksum[32];
-} __attribute__((packed));
-
// Cow operations are currently fixed-size entries, but this may change if
// needed.
struct CowOperation {
@@ -158,16 +158,24 @@
kCowCompressNone = 0,
kCowCompressGz = 1,
kCowCompressBrotli = 2,
- kCowCompressLz4 = 3
+ kCowCompressLz4 = 3,
+ kCowCompressZstd = 4,
};
static constexpr uint8_t kCowReadAheadNotStarted = 0;
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;
- CowFooterData data;
+ uint8_t unused[64];
} __attribute__((packed));
struct ScratchMetadata {
@@ -196,5 +204,8 @@
// Ops that have dependencies on old blocks, and must take care in their merge order
bool IsOrderedOp(const CowOperation& op);
+// Convert compression name to internal value.
+std::optional<CowCompressionAlgorithm> CompressionAlgorithmFromString(std::string_view name);
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index e8e4d72..f4ce52f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -24,47 +24,24 @@
#include <android-base/unique_fd.h>
#include <libsnapshot/cow_format.h>
+namespace chromeos_update_engine {
+class FileDescriptor;
+} // namespace chromeos_update_engine
+
namespace android {
namespace snapshot {
class ICowOpIter;
-// A ByteSink object handles requests for a buffer of a specific size. It
-// always owns the underlying buffer. It's designed to minimize potential
-// copying as we parse or decompress the COW.
-class IByteSink {
- public:
- virtual ~IByteSink() {}
-
- // Called when the reader has data. The size of the request is given. The
- // sink must return a valid pointer (or null on failure), and return the
- // maximum number of bytes that can be written to the returned buffer.
- //
- // The returned buffer is owned by IByteSink, but must remain valid until
- // the read operation has completed (or the entire buffer has been
- // covered by calls to ReturnData).
- //
- // After calling GetBuffer(), all previous buffers returned are no longer
- // valid.
- //
- // GetBuffer() is intended to be sequential. A returned size of N indicates
- // that the output stream will advance by N bytes, and the ReturnData call
- // indicates that those bytes have been fulfilled. Therefore, it is
- // possible to have ReturnBuffer do nothing, if the implementation doesn't
- // care about incremental writes.
- virtual void* GetBuffer(size_t requested, size_t* actual) = 0;
-
- // Called when a section returned by |GetBuffer| has been filled with data.
- virtual bool ReturnData(void* buffer, size_t length) = 0;
-};
-
// Interface for reading from a snapuserd COW.
class ICowReader {
public:
+ using FileDescriptor = chromeos_update_engine::FileDescriptor;
+
virtual ~ICowReader() {}
// Return the file header.
- virtual bool GetHeader(CowHeader* header) = 0;
+ virtual CowHeader& GetHeader() = 0;
// Return the file footer.
virtual bool GetFooter(CowFooter* footer) = 0;
@@ -83,29 +60,55 @@
virtual std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress) = 0;
// Get decoded bytes from the data section, handling any decompression.
- // All retrieved data is passed to the sink.
- virtual bool ReadData(const CowOperation& op, IByteSink* sink) = 0;
+ //
+ // If ignore_bytes is non-zero, it specifies the initial number of bytes
+ // to skip writing to |buffer|.
+ //
+ // Returns the number of bytes written to |buffer|, or -1 on failure.
+ // errno is NOT set.
+ //
+ // Partial reads are not possible unless |buffer_size| is less than the
+ // operation block size.
+ //
+ // 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;
};
-// Iterate over a sequence of COW operations.
+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:
virtual ~ICowOpIter() {}
- // True if there are no more items to read forward, false otherwise.
- virtual bool Done() = 0;
+ // Returns true if the iterator is at the end of the operation list.
+ // If true, Get() and Next() must not be called.
+ virtual bool AtEnd() = 0;
// Read the current operation.
- virtual const CowOperation& Get() = 0;
+ virtual const CowOperation* Get() = 0;
// Advance to the next item.
virtual void Next() = 0;
+ // Returns true if the iterator is at the beginning of the operation list.
+ // If true, Prev() must not be called; Get() however will be valid if
+ // AtEnd() is not true.
+ virtual bool AtBegin() = 0;
+
// Advance to the previous item.
virtual void Prev() = 0;
-
- // True if there are no more items to read backwards, false otherwise
- virtual bool RDone() = 0;
};
class CowReader final : public ICowReader {
@@ -124,12 +127,11 @@
bool Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label = {});
bool InitForMerge(android::base::unique_fd&& fd);
+
bool VerifyMergeOps() override;
-
- bool GetHeader(CowHeader* header) 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
@@ -139,8 +141,12 @@
std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress = false) override;
std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress = false) override;
- bool ReadData(const CowOperation& op, IByteSink* sink) override;
+ ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
+ size_t ignore_bytes = 0) override;
+ 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
@@ -162,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/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index a9682a1..d6194eb 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -1,25 +1,32 @@
-// Copyright (C) 2019 The Android Open Source Project
+// copyright (c) 2019 the android open source project
//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+// 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
+// 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.
+// 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 <stdint.h>
+#include <condition_variable>
#include <cstdint>
+#include <future>
#include <memory>
+#include <mutex>
#include <optional>
+#include <queue>
#include <string>
+#include <thread>
+#include <utility>
+#include <vector>
#include <android-base/unique_fd.h>
#include <libsnapshot/cow_format.h>
@@ -42,36 +49,42 @@
// Preset the number of merged ops. Only useful for testing.
uint64_t num_merge_ops = 0;
+
+ // Number of threads for compression
+ int num_compress_threads = 0;
+
+ // Batch write cluster ops
+ bool batch_write = false;
};
// Interface for writing to a snapuserd COW. All operations are ordered; merges
// will occur in the sequence they were added to the COW.
class ICowWriter {
public:
- explicit ICowWriter(const CowOptions& options) : options_(options) {}
+ using FileDescriptor = chromeos_update_engine::FileDescriptor;
virtual ~ICowWriter() {}
// Encode an operation that copies the contents of |old_block| to the
// location of |new_block|. 'num_blocks' is the number of contiguous
// COPY operations from |old_block| to |new_block|.
- bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1);
+ virtual bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0;
// Encode a sequence of raw blocks. |size| must be a multiple of the block size.
- bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size);
+ virtual bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0;
// Add a sequence of xor'd blocks. |size| must be a multiple of the block size.
- bool AddXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
- uint16_t offset);
+ virtual bool AddXorBlocks(uint32_t new_block_start, const void* data, size_t size,
+ uint32_t old_block, uint16_t offset) = 0;
// Encode a sequence of zeroed blocks. |size| must be a multiple of the block size.
- bool AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks);
+ virtual bool AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) = 0;
// Add a label to the op sequence.
- bool AddLabel(uint64_t label);
+ virtual bool AddLabel(uint64_t label) = 0;
// Add sequence data for op merging. Data is a list of the destination block numbers.
- bool AddSequenceData(size_t num_ops, const uint32_t* data);
+ virtual bool AddSequenceData(size_t num_ops, const uint32_t* data) = 0;
// Flush all pending writes. This must be called before closing the writer
// to ensure that the correct headers and footers are written.
@@ -80,95 +93,66 @@
// Return number of bytes the cow image occupies on disk.
virtual uint64_t GetCowSize() = 0;
- // Returns true if AddCopy() operations are supported.
- virtual bool SupportsCopyOperation() const { return true; }
+ virtual uint32_t GetBlockSize() const = 0;
+ virtual std::optional<uint32_t> GetMaxBlocks() const = 0;
- const CowOptions& options() { return options_; }
+ // Open an ICowReader for this writer. The reader will be a snapshot of the
+ // current operations in the writer; new writes after OpenReader() will not
+ // be reflected.
+ virtual std::unique_ptr<ICowReader> OpenReader() = 0;
- protected:
- virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0;
- virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0;
- virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
- uint32_t old_block, uint16_t offset) = 0;
- virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) = 0;
- virtual bool EmitLabel(uint64_t label) = 0;
- virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) = 0;
-
- bool ValidateNewBlock(uint64_t new_block);
-
- protected:
- CowOptions options_;
+ // Open a file descriptor. This allows reading and seeing through the cow
+ // as if it were a normal file. The optional source_device must be a valid
+ // path if the CowReader contains any copy or xor operations.
+ virtual std::unique_ptr<FileDescriptor> OpenFileDescriptor(
+ const std::optional<std::string>& source_device) = 0;
};
-class CowWriter : public ICowWriter {
+class CompressWorker {
public:
- explicit CowWriter(const CowOptions& options);
+ CompressWorker(CowCompressionAlgorithm compression, uint32_t block_size);
+ bool RunThread();
+ void EnqueueCompressBlocks(const void* buffer, size_t num_blocks);
+ bool GetCompressedBuffers(std::vector<std::basic_string<uint8_t>>* compressed_buf);
+ void Finalize();
+ static std::basic_string<uint8_t> Compress(CowCompressionAlgorithm compression,
+ const void* data, size_t length);
- // Set up the writer.
- // The file starts from the beginning.
- //
- // If fd is < 0, the CowWriter will be opened against /dev/null. This is for
- // computing COW sizes without using storage space.
- bool Initialize(android::base::unique_fd&& fd);
- bool Initialize(android::base::borrowed_fd fd);
- // Set up a writer, assuming that the given label is the last valid label.
- // This will result in dropping any labels that occur after the given on, and will fail
- // if the given label does not appear.
- bool InitializeAppend(android::base::unique_fd&&, uint64_t label);
- bool InitializeAppend(android::base::borrowed_fd fd, uint64_t label);
-
- bool Finalize() override;
-
- uint64_t GetCowSize() override;
-
- uint32_t GetCowVersion() { return header_.major_version; }
-
- protected:
- virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
- virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
- virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
- uint32_t old_block, uint16_t offset) override;
- virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
- virtual bool EmitLabel(uint64_t label) override;
- virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
+ static bool CompressBlocks(CowCompressionAlgorithm compression, size_t block_size,
+ const void* buffer, size_t num_blocks,
+ std::vector<std::basic_string<uint8_t>>* compressed_data);
private:
- bool EmitCluster();
- bool EmitClusterIfNeeded();
- bool EmitBlocks(uint64_t new_block_start, const void* data, size_t size, uint64_t old_block,
- uint16_t offset, uint8_t type);
- void SetupHeaders();
- bool ParseOptions();
- bool OpenForWrite();
- bool OpenForAppend(uint64_t label);
- bool GetDataPos(uint64_t* pos);
- bool WriteRawData(const void* data, size_t size);
- bool WriteOperation(const CowOperation& op, const void* data = nullptr, size_t size = 0);
- void AddOperation(const CowOperation& op);
+ struct CompressWork {
+ const void* buffer;
+ size_t num_blocks;
+ bool compression_status = false;
+ std::vector<std::basic_string<uint8_t>> compressed_data;
+ };
+
+ CowCompressionAlgorithm compression_;
+ uint32_t block_size_;
+
+ std::queue<CompressWork> work_queue_;
+ std::queue<CompressWork> compressed_queue_;
+ std::mutex lock_;
+ std::condition_variable cv_;
+ bool stopped_ = false;
+
std::basic_string<uint8_t> Compress(const void* data, size_t length);
- void InitPos();
-
- bool SetFd(android::base::borrowed_fd fd);
- bool Sync();
- bool Truncate(off_t length);
- bool EnsureSpaceAvailable(const uint64_t bytes_needed) const;
-
- private:
- android::base::unique_fd owned_fd_;
- android::base::borrowed_fd fd_;
- CowHeader header_{};
- CowFooter footer_{};
- CowCompressionAlgorithm compression_ = kCowCompressNone;
- uint64_t next_op_pos_ = 0;
- uint64_t next_data_pos_ = 0;
- uint32_t cluster_size_ = 0;
- uint32_t current_cluster_size_ = 0;
- uint64_t current_data_size_ = 0;
- bool is_dev_null_ = false;
- bool merge_in_progress_ = false;
- bool is_block_device_ = false;
- uint64_t cow_image_size_ = INT64_MAX;
+ bool CompressBlocks(const void* buffer, size_t num_blocks,
+ std::vector<std::basic_string<uint8_t>>* compressed_data);
};
+// Create an ICowWriter not backed by any file. This is useful for estimating
+// the final size of a cow file.
+std::unique_ptr<ICowWriter> CreateCowEstimator(uint32_t version, const CowOptions& options);
+
+// Create an ICowWriter of the given version and options. If a label is given,
+// the writer is opened in append mode.
+std::unique_ptr<ICowWriter> CreateCowWriter(uint32_t version, const CowOptions& options,
+ android::base::unique_fd&& fd,
+ std::optional<uint64_t> label = {});
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h
new file mode 100644
index 0000000..c58c654
--- /dev/null
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_cow_writer.h
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2021 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 <gmock/gmock.h>
+#include <libsnapshot/cow_writer.h>
+
+namespace android::snapshot {
+
+class MockCowWriter : public ICowWriter {
+ public:
+ using FileDescriptor = chromeos_update_engine::FileDescriptor;
+
+ MOCK_METHOD(bool, Finalize, (), (override));
+
+ MOCK_METHOD(uint64_t, GetCowSize, (), (override));
+
+ MOCK_METHOD(bool, AddCopy, (uint64_t, uint64_t, uint64_t), (override));
+ MOCK_METHOD(bool, AddRawBlocks, (uint64_t, const void*, size_t), (override));
+ MOCK_METHOD(bool, AddXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t),
+ (override));
+ MOCK_METHOD(bool, AddZeroBlocks, (uint64_t, uint64_t), (override));
+ MOCK_METHOD(bool, AddLabel, (uint64_t), (override));
+ MOCK_METHOD(bool, AddSequenceData, (size_t, const uint32_t*), (override));
+ MOCK_METHOD(uint32_t, GetBlockSize, (), (override, const));
+ MOCK_METHOD(std::optional<uint32_t>, GetMaxBlocks, (), (override, const));
+
+ MOCK_METHOD(std::unique_ptr<ICowReader>, OpenReader, (), (override));
+ MOCK_METHOD(std::unique_ptr<FileDescriptor>, OpenFileDescriptor,
+ (const std::optional<std::string>&), (override));
+};
+
+} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
index d458b87..ca45d2f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
@@ -42,9 +42,9 @@
(const android::fs_mgr::CreateLogicalPartitionParams& params,
std::string* snapshot_path),
(override));
- MOCK_METHOD(std::unique_ptr<ISnapshotWriter>, OpenSnapshotWriter,
+ MOCK_METHOD(std::unique_ptr<ICowWriter>, OpenSnapshotWriter,
(const android::fs_mgr::CreateLogicalPartitionParams& params,
- const std::optional<std::string>&),
+ std::optional<uint64_t>),
(override));
MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override));
MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override));
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
deleted file mode 100644
index 29828bc..0000000
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Copyright (C) 2021 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 <gmock/gmock.h>
-#include <libsnapshot/snapshot_writer.h>
-
-namespace android::snapshot {
-
-class MockSnapshotWriter : public ISnapshotWriter {
- public:
- using FileDescriptor = ISnapshotWriter::FileDescriptor;
-
- explicit MockSnapshotWriter(const CowOptions& options) : ISnapshotWriter(options) {}
- MockSnapshotWriter() : ISnapshotWriter({}) {}
-
- MOCK_METHOD(bool, Finalize, (), (override));
-
- // Return number of bytes the cow image occupies on disk.
- MOCK_METHOD(uint64_t, GetCowSize, (), (override));
-
- // Returns true if AddCopy() operations are supported.
- MOCK_METHOD(bool, SupportsCopyOperation, (), (const override));
-
- MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t, uint64_t), (override));
- MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override));
- MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t),
- (override));
- MOCK_METHOD(bool, EmitZeroBlocks, (uint64_t, uint64_t), (override));
- MOCK_METHOD(bool, EmitLabel, (uint64_t), (override));
- MOCK_METHOD(bool, EmitSequenceData, (size_t, const uint32_t*), (override));
-
- // Open the writer in write mode (no append).
- MOCK_METHOD(bool, Initialize, (), (override));
- MOCK_METHOD(bool, VerifyMergeOps, (), (override, const, noexcept));
-
- // Open the writer in append mode, with the last label to resume
- // from. See CowWriter::InitializeAppend.
- MOCK_METHOD(bool, InitializeAppend, (uint64_t label), (override));
-
- MOCK_METHOD(std::unique_ptr<FileDescriptor>, OpenReader, (), (override));
-};
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index cdff06e..df532ee 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -33,12 +33,11 @@
#include <libfiemap/image_manager.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
-#include <update_engine/update_metadata.pb.h>
-
#include <libsnapshot/auto_device.h>
+#include <libsnapshot/cow_writer.h>
#include <libsnapshot/return.h>
-#include <libsnapshot/snapshot_writer.h>
#include <snapuserd/snapuserd_client.h>
+#include <update_engine/update_metadata.pb.h>
#ifndef FRIEND_TEST
#define FRIEND_TEST(test_set_name, individual_test) \
@@ -211,16 +210,13 @@
virtual bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params,
std::string* snapshot_path) = 0;
- // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name
+ // Create an ICowWriter to build a snapshot against a target partition. The partition name
// must be suffixed. If a source partition exists, it must be specified as well. The source
// partition will only be used if raw bytes are needed. The source partition should be an
// absolute path to the device, not a partition name.
- //
- // After calling OpenSnapshotWriter, the caller must invoke Initialize or InitializeForAppend
- // before invoking write operations.
- virtual std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter(
+ virtual std::unique_ptr<ICowWriter> OpenSnapshotWriter(
const android::fs_mgr::CreateLogicalPartitionParams& params,
- const std::optional<std::string>& source_device) = 0;
+ std::optional<uint64_t> label = {}) = 0;
// Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot,
// OpenSnapshotWriter. All outstanding open descriptors, writers, or
@@ -362,9 +358,9 @@
Return CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) override;
bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params,
std::string* snapshot_path) override;
- std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter(
+ std::unique_ptr<ICowWriter> OpenSnapshotWriter(
const android::fs_mgr::CreateLogicalPartitionParams& params,
- const std::optional<std::string>& source_device) override;
+ std::optional<uint64_t> label) override;
bool UnmapUpdateSnapshot(const std::string& target_partition_name) override;
bool NeedSnapshotsInFirstStageMount() override;
bool CreateLogicalAndSnapshotPartitions(
@@ -395,6 +391,10 @@
// first-stage to decide whether to launch snapuserd.
bool IsSnapuserdRequired();
+ // This is primarily used to device reboot. If OTA update is in progress,
+ // init will avoid killing processes
+ bool IsUserspaceSnapshotUpdateInProgress();
+
enum class SnapshotDriver {
DM_SNAPSHOT,
DM_USER,
@@ -689,14 +689,10 @@
};
// Helpers for OpenSnapshotWriter.
- std::unique_ptr<ISnapshotWriter> OpenCompressedSnapshotWriter(
- LockedFile* lock, const std::optional<std::string>& source_device,
- const std::string& partition_name, const SnapshotStatus& status,
- const SnapshotPaths& paths);
- std::unique_ptr<ISnapshotWriter> OpenKernelSnapshotWriter(
- LockedFile* lock, const std::optional<std::string>& source_device,
- const std::string& partition_name, const SnapshotStatus& status,
- const SnapshotPaths& paths);
+ std::unique_ptr<ICowWriter> OpenCompressedSnapshotWriter(LockedFile* lock,
+ const SnapshotStatus& status,
+ const SnapshotPaths& paths,
+ std::optional<uint64_t> label);
// Map the base device, COW devices, and snapshot device.
bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params,
@@ -743,7 +739,7 @@
// Initialize snapshots so that they can be mapped later.
// Map the COW partition and zero-initialize the header.
Return InitializeUpdateSnapshots(
- LockedFile* lock, MetadataBuilder* target_metadata,
+ LockedFile* lock, uint32_t cow_version, MetadataBuilder* target_metadata,
const LpMetadata* exported_target_metadata, const std::string& target_suffix,
const std::map<std::string, SnapshotStatus>& all_snapshot_status);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
index 171c7c6..1c9b403 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
@@ -40,9 +40,9 @@
const chromeos_update_engine::DeltaArchiveManifest& manifest) override;
bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params,
std::string* snapshot_path) override;
- std::unique_ptr<ISnapshotWriter> OpenSnapshotWriter(
+ std::unique_ptr<ICowWriter> OpenSnapshotWriter(
const android::fs_mgr::CreateLogicalPartitionParams& params,
- const std::optional<std::string>& source_device) override;
+ std::optional<uint64_t> label) override;
bool UnmapUpdateSnapshot(const std::string& target_partition_name) override;
bool NeedSnapshotsInFirstStageMount() override;
bool CreateLogicalAndSnapshotPartitions(
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
deleted file mode 100644
index 0e3b1db..0000000
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2020 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 <optional>
-
-#include <android-base/unique_fd.h>
-
-#include <libsnapshot/cow_writer.h>
-
-namespace chromeos_update_engine {
-class FileDescriptor;
-} // namespace chromeos_update_engine
-
-namespace android {
-namespace snapshot {
-
-class ISnapshotWriter : public ICowWriter {
- public:
- using FileDescriptor = chromeos_update_engine::FileDescriptor;
-
- explicit ISnapshotWriter(const CowOptions& options);
-
- // Set the source device. This is used for AddCopy() operations, if the
- // underlying writer needs the original bytes (for example if backed by
- // dm-snapshot or if writing directly to an unsnapshotted region). The
- // device is only opened on the first operation that requires it.
- void SetSourceDevice(const std::string& source_device);
-
- // Open the writer in write mode (no append).
- virtual bool Initialize() = 0;
-
- // Open the writer in append mode, with the last label to resume
- // from. See CowWriter::InitializeAppend.
- virtual bool InitializeAppend(uint64_t label) = 0;
-
- virtual std::unique_ptr<FileDescriptor> OpenReader() = 0;
- virtual bool VerifyMergeOps() const noexcept = 0;
-
- protected:
- android::base::borrowed_fd GetSourceFd();
-
- std::optional<std::string> source_device_;
-
- private:
- android::base::unique_fd source_fd_;
-};
-
-// Send writes to a COW or a raw device directly, based on a threshold.
-class CompressedSnapshotWriter final : public ISnapshotWriter {
- public:
- CompressedSnapshotWriter(const CowOptions& options);
-
- // Sets the COW device; this is required.
- bool SetCowDevice(android::base::unique_fd&& cow_device);
-
- bool Initialize() override;
- bool InitializeAppend(uint64_t label) override;
- bool Finalize() override;
- uint64_t GetCowSize() override;
- std::unique_ptr<FileDescriptor> OpenReader() override;
- bool VerifyMergeOps() const noexcept;
-
- protected:
- bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
- bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
- bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
- uint16_t offset) override;
- bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
- bool EmitLabel(uint64_t label) override;
- bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
-
- private:
- std::unique_ptr<CowReader> OpenCowReader() const;
- android::base::unique_fd cow_device_;
-
- std::unique_ptr<CowWriter> cow_;
-};
-
-// Write directly to a dm-snapshot device.
-class OnlineKernelSnapshotWriter final : public ISnapshotWriter {
- public:
- OnlineKernelSnapshotWriter(const CowOptions& options);
-
- // Set the device used for all writes.
- void SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, uint64_t cow_size);
-
- bool Initialize() override { return true; }
- bool InitializeAppend(uint64_t) override { return true; }
-
- bool Finalize() override;
- uint64_t GetCowSize() override { return cow_size_; }
- std::unique_ptr<FileDescriptor> OpenReader() override;
-
- // Online kernel snapshot writer doesn't care about merge sequences.
- // So ignore.
- bool VerifyMergeOps() const noexcept override { return true; }
-
- protected:
- bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
- bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
- bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
- uint16_t offset) override;
- bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
- bool EmitLabel(uint64_t label) override;
- bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
-
- private:
- android::base::unique_fd snapshot_fd_;
- uint64_t cow_size_ = 0;
-};
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index f850b94..5e9f049 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -143,6 +143,9 @@
virtual DmDeviceState GetState(const std::string& name) const override {
return impl_.GetState(name);
}
+ virtual bool LoadTable(const std::string& name, const DmTable& table) {
+ return impl_.LoadTable(name, table);
+ }
virtual bool LoadTableAndActivate(const std::string& name, const DmTable& table) {
return impl_.LoadTableAndActivate(name, table);
}
@@ -195,7 +198,7 @@
// Expect space of |path| is multiple of 4K.
bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size = std::nullopt,
std::string* hash = nullptr);
-std::string HashSnapshot(ISnapshotWriter* writer);
+std::string HashSnapshot(ICowWriter::FileDescriptor* writer);
std::string ToHexString(const uint8_t* buf, size_t len);
@@ -211,29 +214,6 @@
// Get partition size from update package metadata.
uint64_t GetSize(PartitionUpdate* partition_update);
-// Util class for test cases on low space scenario. These tests assumes image manager
-// uses /data as backup device.
-class LowSpaceUserdata {
- public:
- // Set the maximum free space allowed for this test. If /userdata has more space than the given
- // number, a file is allocated to consume space.
- AssertionResult Init(uint64_t max_free_space);
-
- uint64_t free_space() const;
- uint64_t available_space() const;
- uint64_t bsize() const;
-
- private:
- AssertionResult ReadUserdataStats();
-
- static constexpr const char* kUserDataDevice = "/data";
- std::unique_ptr<TemporaryFile> big_file_;
- bool initialized_ = false;
- uint64_t free_space_ = 0;
- uint64_t available_space_ = 0;
- uint64_t bsize_ = 0;
-};
-
bool IsVirtualAbEnabled();
#define SKIP_IF_NON_VIRTUAL_AB() \
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index 0eb231b..a4a0ad6 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -29,12 +29,34 @@
#include <libsnapshot/cow_writer.h>
#include <lz4.h>
#include <zlib.h>
+#include <zstd.h>
namespace android {
namespace snapshot {
-std::basic_string<uint8_t> CowWriter::Compress(const void* data, size_t length) {
- switch (compression_) {
+std::optional<CowCompressionAlgorithm> CompressionAlgorithmFromString(std::string_view name) {
+ if (name == "gz") {
+ return {kCowCompressGz};
+ } else if (name == "brotli") {
+ return {kCowCompressBrotli};
+ } else if (name == "lz4") {
+ return {kCowCompressLz4};
+ } else if (name == "zstd") {
+ return {kCowCompressZstd};
+ } else if (name == "none" || name.empty()) {
+ return {kCowCompressNone};
+ } else {
+ return {};
+ }
+}
+
+std::basic_string<uint8_t> CompressWorker::Compress(const void* data, size_t length) {
+ return Compress(compression_, data, length);
+}
+
+std::basic_string<uint8_t> CompressWorker::Compress(CowCompressionAlgorithm compression,
+ const void* data, size_t length) {
+ switch (compression) {
case kCowCompressGz: {
const auto bound = compressBound(length);
std::basic_string<uint8_t> buffer(bound, '\0');
@@ -93,12 +115,148 @@
}
return buffer;
}
+ case kCowCompressZstd: {
+ std::basic_string<uint8_t> buffer(ZSTD_compressBound(length), '\0');
+ const auto compressed_size =
+ ZSTD_compress(buffer.data(), buffer.size(), data, length, 0);
+ if (compressed_size <= 0) {
+ LOG(ERROR) << "ZSTD compression failed " << compressed_size;
+ return {};
+ }
+ // Don't run compression if the compressed output is larger
+ if (compressed_size >= length) {
+ buffer.resize(length);
+ memcpy(buffer.data(), data, length);
+ } else {
+ buffer.resize(compressed_size);
+ }
+ return buffer;
+ }
default:
- LOG(ERROR) << "unhandled compression type: " << compression_;
+ LOG(ERROR) << "unhandled compression type: " << compression;
break;
}
return {};
}
+bool CompressWorker::CompressBlocks(const void* buffer, size_t num_blocks,
+ std::vector<std::basic_string<uint8_t>>* compressed_data) {
+ return CompressBlocks(compression_, block_size_, buffer, num_blocks, compressed_data);
+}
+
+bool CompressWorker::CompressBlocks(CowCompressionAlgorithm compression, size_t block_size,
+ const void* buffer, size_t num_blocks,
+ std::vector<std::basic_string<uint8_t>>* compressed_data) {
+ const uint8_t* iter = reinterpret_cast<const uint8_t*>(buffer);
+ while (num_blocks) {
+ auto data = Compress(compression, iter, block_size);
+ if (data.empty()) {
+ PLOG(ERROR) << "CompressBlocks: Compression failed";
+ return false;
+ }
+ if (data.size() > std::numeric_limits<uint16_t>::max()) {
+ LOG(ERROR) << "Compressed block is too large: " << data.size();
+ return false;
+ }
+
+ compressed_data->emplace_back(std::move(data));
+ num_blocks -= 1;
+ iter += block_size;
+ }
+ return true;
+}
+
+bool CompressWorker::RunThread() {
+ while (true) {
+ // Wait for work
+ CompressWork blocks;
+ {
+ std::unique_lock<std::mutex> lock(lock_);
+ while (work_queue_.empty() && !stopped_) {
+ cv_.wait(lock);
+ }
+
+ if (stopped_) {
+ return true;
+ }
+
+ blocks = std::move(work_queue_.front());
+ work_queue_.pop();
+ }
+
+ // Compress blocks
+ bool ret = CompressBlocks(blocks.buffer, blocks.num_blocks, &blocks.compressed_data);
+ blocks.compression_status = ret;
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ compressed_queue_.push(std::move(blocks));
+ }
+
+ // Notify completion
+ cv_.notify_all();
+
+ if (!ret) {
+ LOG(ERROR) << "CompressBlocks failed";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void CompressWorker::EnqueueCompressBlocks(const void* buffer, size_t num_blocks) {
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ CompressWork blocks = {};
+ blocks.buffer = buffer;
+ blocks.num_blocks = num_blocks;
+ work_queue_.push(std::move(blocks));
+ }
+ cv_.notify_all();
+}
+
+bool CompressWorker::GetCompressedBuffers(std::vector<std::basic_string<uint8_t>>* compressed_buf) {
+ {
+ std::unique_lock<std::mutex> lock(lock_);
+ while (compressed_queue_.empty() && !stopped_) {
+ cv_.wait(lock);
+ }
+
+ if (stopped_) {
+ return true;
+ }
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ while (compressed_queue_.size() > 0) {
+ CompressWork blocks = std::move(compressed_queue_.front());
+ compressed_queue_.pop();
+
+ if (blocks.compression_status) {
+ compressed_buf->insert(compressed_buf->end(),
+ std::make_move_iterator(blocks.compressed_data.begin()),
+ std::make_move_iterator(blocks.compressed_data.end()));
+ } else {
+ LOG(ERROR) << "Block compression failed";
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void CompressWorker::Finalize() {
+ {
+ std::unique_lock<std::mutex> lock(lock_);
+ stopped_ = true;
+ }
+ cv_.notify_all();
+}
+
+CompressWorker::CompressWorker(CowCompressionAlgorithm compression, uint32_t block_size)
+ : compression_(compression), block_size_(block_size) {}
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
index 139a29f..da90cc0 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
@@ -16,124 +16,122 @@
#include "cow_decompress.h"
+#include <array>
+#include <cstring>
#include <utility>
+#include <vector>
#include <android-base/logging.h>
#include <brotli/decode.h>
#include <lz4.h>
#include <zlib.h>
+#include <zstd.h>
namespace android {
namespace snapshot {
-class NoDecompressor final : public IDecompressor {
- public:
- bool Decompress(size_t) override;
-};
+ssize_t IByteStream::ReadFully(void* buffer, size_t buffer_size) {
+ size_t stream_remaining = Size();
-bool NoDecompressor::Decompress(size_t) {
- size_t stream_remaining = stream_->Size();
+ char* buffer_start = reinterpret_cast<char*>(buffer);
+ char* buffer_pos = buffer_start;
+ size_t buffer_remaining = buffer_size;
while (stream_remaining) {
- size_t buffer_size = stream_remaining;
- uint8_t* buffer = reinterpret_cast<uint8_t*>(sink_->GetBuffer(buffer_size, &buffer_size));
- if (!buffer) {
- LOG(ERROR) << "Could not acquire buffer from sink";
- return false;
+ const size_t to_read = std::min(buffer_remaining, stream_remaining);
+ const ssize_t actual_read = Read(buffer_pos, to_read);
+ if (actual_read < 0) {
+ return -1;
}
+ if (!actual_read) {
+ LOG(ERROR) << "Stream ended prematurely";
+ return -1;
+ }
+ CHECK_LE(actual_read, to_read);
- // Read until we can fill the buffer.
- uint8_t* buffer_pos = buffer;
- size_t bytes_to_read = std::min(buffer_size, stream_remaining);
- while (bytes_to_read) {
- size_t read;
- if (!stream_->Read(buffer_pos, bytes_to_read, &read)) {
- return false;
- }
- if (!read) {
- LOG(ERROR) << "Stream ended prematurely";
- return false;
- }
- if (!sink_->ReturnData(buffer_pos, read)) {
- LOG(ERROR) << "Could not return buffer to sink";
- return false;
- }
- buffer_pos += read;
- bytes_to_read -= read;
- stream_remaining -= read;
- }
+ stream_remaining -= actual_read;
+ buffer_pos += actual_read;
+ buffer_remaining -= actual_read;
}
- return true;
+ return buffer_pos - buffer_start;
}
-std::unique_ptr<IDecompressor> IDecompressor::Uncompressed() {
- return std::unique_ptr<IDecompressor>(new NoDecompressor());
+std::unique_ptr<IDecompressor> IDecompressor::FromString(std::string_view compressor) {
+ if (compressor == "lz4") {
+ return IDecompressor::Lz4();
+ } else if (compressor == "brotli") {
+ return IDecompressor::Brotli();
+ } else if (compressor == "gz") {
+ return IDecompressor::Gz();
+ } else {
+ return nullptr;
+ }
}
// Read chunks of the COW and incrementally stream them to the decoder.
class StreamDecompressor : public IDecompressor {
public:
- bool Decompress(size_t output_bytes) override;
+ ssize_t Decompress(void* buffer, size_t buffer_size, size_t decompressed_size,
+ size_t ignore_bytes) override;
virtual bool Init() = 0;
- virtual bool DecompressInput(const uint8_t* data, size_t length) = 0;
- virtual bool Done() = 0;
+ virtual bool PartialDecompress(const uint8_t* data, size_t length) = 0;
+ bool OutputFull() const { return !ignore_bytes_ && !output_buffer_remaining_; }
protected:
- bool GetFreshBuffer();
-
- size_t output_bytes_;
size_t stream_remaining_;
uint8_t* output_buffer_ = nullptr;
size_t output_buffer_remaining_ = 0;
+ size_t ignore_bytes_ = 0;
+ bool decompressor_ended_ = false;
};
static constexpr size_t kChunkSize = 4096;
-bool StreamDecompressor::Decompress(size_t output_bytes) {
+ssize_t StreamDecompressor::Decompress(void* buffer, size_t buffer_size, size_t,
+ size_t ignore_bytes) {
if (!Init()) {
return false;
}
stream_remaining_ = stream_->Size();
- output_bytes_ = output_bytes;
+ output_buffer_ = reinterpret_cast<uint8_t*>(buffer);
+ output_buffer_remaining_ = buffer_size;
+ ignore_bytes_ = ignore_bytes;
uint8_t chunk[kChunkSize];
- while (stream_remaining_) {
- size_t read = std::min(stream_remaining_, sizeof(chunk));
- if (!stream_->Read(chunk, read, &read)) {
- return false;
+ while (stream_remaining_ && output_buffer_remaining_ && !decompressor_ended_) {
+ size_t max_read = std::min(stream_remaining_, sizeof(chunk));
+ ssize_t read = stream_->Read(chunk, max_read);
+ if (read < 0) {
+ return -1;
}
if (!read) {
LOG(ERROR) << "Stream ended prematurely";
- return false;
+ return -1;
}
- if (!DecompressInput(chunk, read)) {
- return false;
+ if (!PartialDecompress(chunk, read)) {
+ return -1;
}
-
stream_remaining_ -= read;
+ }
- if (stream_remaining_ && Done()) {
+ if (stream_remaining_) {
+ if (decompressor_ended_ && !OutputFull()) {
+ // If there's more input in the stream, but we haven't finished
+ // consuming ignored bytes or available output space yet, then
+ // something weird happened. Report it and fail.
LOG(ERROR) << "Decompressor terminated early";
- return false;
+ return -1;
+ }
+ } else {
+ if (!decompressor_ended_ && !OutputFull()) {
+ // The stream ended, but the decoder doesn't think so, and there are
+ // more bytes in the output buffer.
+ LOG(ERROR) << "Decompressor expected more bytes";
+ return -1;
}
}
- if (!Done()) {
- LOG(ERROR) << "Decompressor expected more bytes";
- return false;
- }
- return true;
-}
-
-bool StreamDecompressor::GetFreshBuffer() {
- size_t request_size = std::min(output_bytes_, kChunkSize);
- output_buffer_ =
- reinterpret_cast<uint8_t*>(sink_->GetBuffer(request_size, &output_buffer_remaining_));
- if (!output_buffer_) {
- LOG(ERROR) << "Could not acquire buffer from sink";
- return false;
- }
- return true;
+ return buffer_size - output_buffer_remaining_;
}
class GzDecompressor final : public StreamDecompressor {
@@ -141,12 +139,10 @@
~GzDecompressor();
bool Init() override;
- bool DecompressInput(const uint8_t* data, size_t length) override;
- bool Done() override { return ended_; }
+ bool PartialDecompress(const uint8_t* data, size_t length) override;
private:
z_stream z_ = {};
- bool ended_ = false;
};
bool GzDecompressor::Init() {
@@ -161,23 +157,39 @@
inflateEnd(&z_);
}
-bool GzDecompressor::DecompressInput(const uint8_t* data, size_t length) {
+bool GzDecompressor::PartialDecompress(const uint8_t* data, size_t length) {
z_.next_in = reinterpret_cast<Bytef*>(const_cast<uint8_t*>(data));
z_.avail_in = length;
- while (z_.avail_in) {
- // If no more output buffer, grab a new buffer.
- if (z_.avail_out == 0) {
- if (!GetFreshBuffer()) {
- return false;
- }
- z_.next_out = reinterpret_cast<Bytef*>(output_buffer_);
- z_.avail_out = output_buffer_remaining_;
+ // If we're asked to ignore starting bytes, we sink those into the output
+ // repeatedly until there is nothing left to ignore.
+ while (ignore_bytes_ && z_.avail_in) {
+ std::array<Bytef, kChunkSize> ignore_buffer;
+ size_t max_ignore = std::min(ignore_bytes_, ignore_buffer.size());
+ z_.next_out = ignore_buffer.data();
+ z_.avail_out = max_ignore;
+
+ int rv = inflate(&z_, Z_NO_FLUSH);
+ if (rv != Z_OK && rv != Z_STREAM_END) {
+ LOG(ERROR) << "inflate returned error code " << rv;
+ return false;
}
- // Remember the position of the output buffer so we can call ReturnData.
- auto avail_out = z_.avail_out;
+ size_t returned = max_ignore - z_.avail_out;
+ CHECK_LE(returned, ignore_bytes_);
+ ignore_bytes_ -= returned;
+
+ if (rv == Z_STREAM_END) {
+ decompressor_ended_ = true;
+ return true;
+ }
+ }
+
+ z_.next_out = reinterpret_cast<Bytef*>(output_buffer_);
+ z_.avail_out = output_buffer_remaining_;
+
+ while (z_.avail_in && z_.avail_out) {
// Decompress.
int rv = inflate(&z_, Z_NO_FLUSH);
if (rv != Z_OK && rv != Z_STREAM_END) {
@@ -185,20 +197,14 @@
return false;
}
- size_t returned = avail_out - z_.avail_out;
- if (!sink_->ReturnData(output_buffer_, returned)) {
- LOG(ERROR) << "Could not return buffer to sink";
- return false;
- }
+ size_t returned = output_buffer_remaining_ - z_.avail_out;
+ CHECK_LE(returned, output_buffer_remaining_);
+
output_buffer_ += returned;
output_buffer_remaining_ -= returned;
if (rv == Z_STREAM_END) {
- if (z_.avail_in) {
- LOG(ERROR) << "Gz stream ended prematurely";
- return false;
- }
- ended_ = true;
+ decompressor_ended_ = true;
return true;
}
}
@@ -214,8 +220,7 @@
~BrotliDecompressor();
bool Init() override;
- bool DecompressInput(const uint8_t* data, size_t length) override;
- bool Done() override { return BrotliDecoderIsFinished(decoder_); }
+ bool PartialDecompress(const uint8_t* data, size_t length) override;
private:
BrotliDecoderState* decoder_ = nullptr;
@@ -232,28 +237,41 @@
}
}
-bool BrotliDecompressor::DecompressInput(const uint8_t* data, size_t length) {
+bool BrotliDecompressor::PartialDecompress(const uint8_t* data, size_t length) {
size_t available_in = length;
const uint8_t* next_in = data;
- bool needs_more_output = false;
- while (available_in || needs_more_output) {
- if (!output_buffer_remaining_ && !GetFreshBuffer()) {
+ while (available_in && ignore_bytes_ && !BrotliDecoderIsFinished(decoder_)) {
+ std::array<uint8_t, kChunkSize> ignore_buffer;
+ size_t max_ignore = std::min(ignore_bytes_, ignore_buffer.size());
+ size_t ignore_size = max_ignore;
+
+ uint8_t* ignore_buffer_ptr = ignore_buffer.data();
+ auto r = BrotliDecoderDecompressStream(decoder_, &available_in, &next_in, &ignore_size,
+ &ignore_buffer_ptr, nullptr);
+ if (r == BROTLI_DECODER_RESULT_ERROR) {
+ LOG(ERROR) << "brotli decode failed";
+ return false;
+ } else if (r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && available_in) {
+ LOG(ERROR) << "brotli unexpected needs more input";
return false;
}
+ ignore_bytes_ -= max_ignore - ignore_size;
+ }
- auto output_buffer = output_buffer_;
+ while (available_in && !BrotliDecoderIsFinished(decoder_)) {
auto r = BrotliDecoderDecompressStream(decoder_, &available_in, &next_in,
&output_buffer_remaining_, &output_buffer_, nullptr);
if (r == BROTLI_DECODER_RESULT_ERROR) {
LOG(ERROR) << "brotli decode failed";
return false;
- }
- if (!sink_->ReturnData(output_buffer, output_buffer_ - output_buffer)) {
+ } else if (r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && available_in) {
+ LOG(ERROR) << "brotli unexpected needs more input";
return false;
}
- needs_more_output = (r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT);
}
+
+ decompressor_ended_ = BrotliDecoderIsFinished(decoder_);
return true;
}
@@ -265,44 +283,101 @@
public:
~Lz4Decompressor() override = default;
- bool Decompress(const size_t output_size) override {
- size_t actual_buffer_size = 0;
- auto&& output_buffer = sink_->GetBuffer(output_size, &actual_buffer_size);
- if (actual_buffer_size != output_size) {
- LOG(ERROR) << "Failed to allocate buffer of size " << output_size << " only got "
- << actual_buffer_size << " bytes";
- return false;
+ ssize_t Decompress(void* buffer, size_t buffer_size, size_t decompressed_size,
+ size_t ignore_bytes) override {
+ std::string input_buffer(stream_->Size(), '\0');
+ ssize_t streamed_in = stream_->ReadFully(input_buffer.data(), input_buffer.size());
+ if (streamed_in < 0) {
+ return -1;
}
- // If input size is same as output size, then input is uncompressed.
- if (stream_->Size() == output_size) {
- size_t bytes_read = 0;
- stream_->Read(output_buffer, output_size, &bytes_read);
- if (bytes_read != output_size) {
- LOG(ERROR) << "Failed to read all input at once. Expected: " << output_size
- << " actual: " << bytes_read;
- return false;
+ CHECK_EQ(streamed_in, stream_->Size());
+
+ char* decode_buffer = reinterpret_cast<char*>(buffer);
+ size_t decode_buffer_size = buffer_size;
+
+ // It's unclear if LZ4 can exactly satisfy a partial decode request, so
+ // if we get one, create a temporary buffer.
+ std::string temp;
+ if (buffer_size < decompressed_size) {
+ temp.resize(decompressed_size, '\0');
+ decode_buffer = temp.data();
+ decode_buffer_size = temp.size();
+ }
+
+ const int bytes_decompressed = LZ4_decompress_safe(input_buffer.data(), decode_buffer,
+ input_buffer.size(), decode_buffer_size);
+ if (bytes_decompressed < 0) {
+ LOG(ERROR) << "Failed to decompress LZ4 block, code: " << bytes_decompressed;
+ return -1;
+ }
+ if (bytes_decompressed != decompressed_size) {
+ LOG(ERROR) << "Failed to decompress LZ4 block, expected output size: "
+ << bytes_decompressed << ", actual: " << bytes_decompressed;
+ return -1;
+ }
+ CHECK_LE(bytes_decompressed, decode_buffer_size);
+
+ if (ignore_bytes > bytes_decompressed) {
+ LOG(ERROR) << "Ignoring more bytes than exist in stream (ignoring " << ignore_bytes
+ << ", got " << bytes_decompressed << ")";
+ return -1;
+ }
+
+ if (temp.empty()) {
+ // LZ4's API has no way to sink out the first N bytes of decoding,
+ // so we read them all in and memmove() to drop the partial read.
+ if (ignore_bytes) {
+ memmove(decode_buffer, decode_buffer + ignore_bytes,
+ bytes_decompressed - ignore_bytes);
}
- sink_->ReturnData(output_buffer, output_size);
- return true;
+ return bytes_decompressed - ignore_bytes;
}
+
+ size_t max_copy = std::min(bytes_decompressed - ignore_bytes, buffer_size);
+ memcpy(buffer, temp.data() + ignore_bytes, max_copy);
+ return max_copy;
+ }
+};
+
+class ZstdDecompressor final : public IDecompressor {
+ public:
+ ssize_t Decompress(void* buffer, size_t buffer_size, size_t decompressed_size,
+ size_t ignore_bytes = 0) override {
+ if (buffer_size < decompressed_size - ignore_bytes) {
+ LOG(INFO) << "buffer size " << buffer_size
+ << " is not large enough to hold decompressed data. Decompressed size "
+ << decompressed_size << ", ignore_bytes " << ignore_bytes;
+ return -1;
+ }
+ if (ignore_bytes == 0) {
+ if (!Decompress(buffer, decompressed_size)) {
+ return -1;
+ }
+ return decompressed_size;
+ }
+ std::vector<unsigned char> ignore_buf(decompressed_size);
+ if (!Decompress(buffer, decompressed_size)) {
+ return -1;
+ }
+ memcpy(buffer, ignore_buf.data() + ignore_bytes, buffer_size);
+ return decompressed_size;
+ }
+ bool Decompress(void* output_buffer, const size_t output_size) {
std::string input_buffer;
input_buffer.resize(stream_->Size());
- size_t bytes_read = 0;
- stream_->Read(input_buffer.data(), input_buffer.size(), &bytes_read);
+ size_t bytes_read = stream_->Read(input_buffer.data(), input_buffer.size());
if (bytes_read != input_buffer.size()) {
LOG(ERROR) << "Failed to read all input at once. Expected: " << input_buffer.size()
<< " actual: " << bytes_read;
return false;
}
- const int bytes_decompressed =
- LZ4_decompress_safe(input_buffer.data(), static_cast<char*>(output_buffer),
- input_buffer.size(), output_size);
+ const auto bytes_decompressed = ZSTD_decompress(output_buffer, output_size,
+ input_buffer.data(), input_buffer.size());
if (bytes_decompressed != output_size) {
- LOG(ERROR) << "Failed to decompress LZ4 block, expected output size: " << output_size
+ LOG(ERROR) << "Failed to decompress ZSTD block, expected output size: " << output_size
<< ", actual: " << bytes_decompressed;
return false;
}
- sink_->ReturnData(output_buffer, output_size);
return true;
}
};
@@ -311,5 +386,9 @@
return std::make_unique<Lz4Decompressor>();
}
+std::unique_ptr<IDecompressor> IDecompressor::Zstd() {
+ return std::make_unique<ZstdDecompressor>();
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.h b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.h
index 7f74eda..52b3d76 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.h
@@ -26,11 +26,16 @@
virtual ~IByteStream() {}
// Read up to |length| bytes, storing the number of bytes read in the out-
- // parameter. If the end of the stream is reached, 0 is returned.
- virtual bool Read(void* buffer, size_t length, size_t* read) = 0;
+ // parameter. If the end of the stream is reached, 0 is returned. On error,
+ // -1 is returned. errno is NOT set.
+ virtual ssize_t Read(void* buffer, size_t length) = 0;
// Size of the stream.
virtual size_t Size() const = 0;
+
+ // Helper for Read(). Read the entire stream into |buffer|, up to |length|
+ // bytes.
+ ssize_t ReadFully(void* buffer, size_t length);
};
class IDecompressor {
@@ -42,16 +47,24 @@
static std::unique_ptr<IDecompressor> Gz();
static std::unique_ptr<IDecompressor> Brotli();
static std::unique_ptr<IDecompressor> Lz4();
+ static std::unique_ptr<IDecompressor> Zstd();
- // |output_bytes| is the expected total number of bytes to sink.
- virtual bool Decompress(size_t output_bytes) = 0;
+ static std::unique_ptr<IDecompressor> FromString(std::string_view compressor);
+
+ // Decompress at most |buffer_size| bytes, ignoring the first |ignore_bytes|
+ // of the decoded stream. |buffer_size| must be at least one byte.
+ // |decompressed_size| is the expected total size if the entire stream were
+ // decompressed.
+ //
+ // Returns the number of bytes written to |buffer|, or -1 on error. errno
+ // is NOT set.
+ virtual ssize_t Decompress(void* buffer, size_t buffer_size, size_t decompressed_size,
+ size_t ignore_bytes = 0) = 0;
void set_stream(IByteStream* stream) { stream_ = stream; }
- void set_sink(IByteSink* sink) { sink_ = sink; }
protected:
IByteStream* stream_ = nullptr;
- IByteSink* sink_ = nullptr;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
index 94c4109..ff3ccec 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
@@ -19,10 +19,13 @@
#include <unistd.h>
#include <android-base/logging.h>
+#include "writer_v2.h"
namespace android {
namespace snapshot {
+using android::base::unique_fd;
+
std::ostream& operator<<(std::ostream& os, CowOperation const& op) {
os << "CowOperation(type:";
if (op.type == kCowCopyOp)
@@ -57,8 +60,6 @@
os << "data_length:" << op.data_length << ",\t";
os << "new_block:" << op.new_block << ",\t";
os << "source:" << op.source;
- if (op.type == kCowXorOp)
- os << " (block:" << op.source / BLOCK_SZ << " offset:" << op.source % BLOCK_SZ << ")";
os << ")";
return os;
}
@@ -105,5 +106,27 @@
}
}
+std::unique_ptr<ICowWriter> CreateCowWriter(uint32_t version, const CowOptions& options,
+ unique_fd&& fd, std::optional<uint64_t> label) {
+ std::unique_ptr<CowWriterBase> base;
+ switch (version) {
+ case 1:
+ case 2:
+ base = std::make_unique<CowWriterV2>(options, std::move(fd));
+ break;
+ default:
+ LOG(ERROR) << "Cannot create unknown cow version: " << version;
+ return nullptr;
+ }
+ if (!base->Initialize(label)) {
+ return nullptr;
+ }
+ return base;
+}
+
+std::unique_ptr<ICowWriter> CreateCowEstimator(uint32_t version, const CowOptions& options) {
+ return CreateCowWriter(version, options, unique_fd{-1}, std::nullopt);
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
index 45be191..489669a 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
@@ -30,6 +30,7 @@
#include <zlib.h>
#include "cow_decompress.h"
+#include "parser_v2.h"
namespace android {
namespace snapshot {
@@ -42,15 +43,6 @@
reader_flag_(reader_flag),
is_merge_(is_merge) {}
-static void SHA256(const void*, size_t, uint8_t[]) {
-#if 0
- SHA256_CTX c;
- SHA256_Init(&c);
- SHA256_Update(&c, data, length);
- SHA256_Final(out, &c);
-#endif
-}
-
std::unique_ptr<CowReader> CowReader::CloneCowReader() {
auto cow = std::make_unique<CowReader>();
cow->owned_fd_.reset();
@@ -62,7 +54,6 @@
cow->merge_op_start_ = merge_op_start_;
cow->num_total_data_ops_ = num_total_data_ops_;
cow->num_ordered_ops_to_merge_ = num_ordered_ops_to_merge_;
- cow->has_seq_ops_ = has_seq_ops_;
cow->data_loc_ = data_loc_;
cow->block_pos_index_ = block_pos_index_;
cow->is_merge_ = is_merge_;
@@ -100,217 +91,26 @@
bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label) {
fd_ = fd;
- auto pos = lseek(fd_.get(), 0, SEEK_END);
- if (pos < 0) {
- PLOG(ERROR) << "lseek end failed";
- return false;
- }
- fd_size_ = pos;
-
- if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek header failed";
- return false;
- }
- if (!android::base::ReadFully(fd_, &header_, sizeof(header_))) {
- PLOG(ERROR) << "read header failed";
+ if (!ReadCowHeader(fd, &header_)) {
return false;
}
- if (header_.magic != kCowMagicNumber) {
- LOG(ERROR) << "Header Magic corrupted. Magic: " << header_.magic
- << "Expected: " << kCowMagicNumber;
- return false;
- }
- if (header_.footer_size != sizeof(CowFooter)) {
- LOG(ERROR) << "Footer size unknown, read " << header_.footer_size << ", expected "
- << sizeof(CowFooter);
- return false;
- }
- if (header_.op_size != sizeof(CowOperation)) {
- LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
- << sizeof(CowOperation);
- return false;
- }
- if (header_.cluster_ops == 1) {
- LOG(ERROR) << "Clusters must contain at least two operations to function.";
- return false;
- }
- if (header_.op_size != sizeof(CowOperation)) {
- LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
- << sizeof(CowOperation);
- return false;
- }
- if (header_.cluster_ops == 1) {
- LOG(ERROR) << "Clusters must contain at least two operations to function.";
+ CowParserV2 parser;
+ if (!parser.Parse(fd, header_, label)) {
return false;
}
- if ((header_.major_version > kCowVersionMajor) || (header_.minor_version != kCowVersionMinor)) {
- LOG(ERROR) << "Header version mismatch";
- LOG(ERROR) << "Major version: " << header_.major_version
- << "Expected: " << kCowVersionMajor;
- LOG(ERROR) << "Minor version: " << header_.minor_version
- << "Expected: " << kCowVersionMinor;
- return false;
- }
+ footer_ = parser.footer();
+ fd_size_ = parser.fd_size();
+ last_label_ = parser.last_label();
+ ops_ = std::move(parser.ops());
+ data_loc_ = parser.data_loc();
- if (!ParseOps(label)) {
- return false;
- }
// If we're resuming a write, we're not ready to merge
if (label.has_value()) return true;
return PrepMergeOps();
}
-bool CowReader::ParseOps(std::optional<uint64_t> label) {
- uint64_t pos;
- auto data_loc = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
-
- // Skip the scratch space
- if (header_.major_version >= 2 && (header_.buffer_size > 0)) {
- LOG(DEBUG) << " Scratch space found of size: " << header_.buffer_size;
- size_t init_offset = header_.header_size + header_.buffer_size;
- pos = lseek(fd_.get(), init_offset, SEEK_SET);
- if (pos != init_offset) {
- PLOG(ERROR) << "lseek ops failed";
- return false;
- }
- } else {
- pos = lseek(fd_.get(), header_.header_size, SEEK_SET);
- if (pos != header_.header_size) {
- PLOG(ERROR) << "lseek ops failed";
- return false;
- }
- // Reading a v1 version of COW which doesn't have buffer_size.
- header_.buffer_size = 0;
- }
- uint64_t data_pos = 0;
-
- if (header_.cluster_ops) {
- data_pos = pos + header_.cluster_ops * sizeof(CowOperation);
- } else {
- data_pos = pos + sizeof(CowOperation);
- }
-
- auto ops_buffer = std::make_shared<std::vector<CowOperation>>();
- uint64_t current_op_num = 0;
- uint64_t cluster_ops = header_.cluster_ops ?: 1;
- bool done = false;
-
- // Alternating op clusters and data
- while (!done) {
- uint64_t to_add = std::min(cluster_ops, (fd_size_ - pos) / sizeof(CowOperation));
- if (to_add == 0) break;
- ops_buffer->resize(current_op_num + to_add);
- if (!android::base::ReadFully(fd_, &ops_buffer->data()[current_op_num],
- to_add * sizeof(CowOperation))) {
- PLOG(ERROR) << "read op failed";
- return false;
- }
- // Parse current cluster to find start of next cluster
- while (current_op_num < ops_buffer->size()) {
- auto& current_op = ops_buffer->data()[current_op_num];
- current_op_num++;
- if (current_op.type == kCowXorOp) {
- data_loc->insert({current_op.new_block, data_pos});
- }
- pos += sizeof(CowOperation) + GetNextOpOffset(current_op, header_.cluster_ops);
- data_pos += current_op.data_length + GetNextDataOffset(current_op, header_.cluster_ops);
-
- if (current_op.type == kCowClusterOp) {
- break;
- } else if (current_op.type == kCowLabelOp) {
- last_label_ = {current_op.source};
-
- // If we reach the requested label, stop reading.
- if (label && label.value() == current_op.source) {
- done = true;
- break;
- }
- } else if (current_op.type == kCowFooterOp) {
- footer_.emplace();
- CowFooter* footer = &footer_.value();
- memcpy(&footer_->op, ¤t_op, sizeof(footer->op));
- off_t offs = lseek(fd_.get(), pos, SEEK_SET);
- if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
- PLOG(ERROR) << "lseek next op failed " << offs;
- return false;
- }
- if (!android::base::ReadFully(fd_, &footer->data, sizeof(footer->data))) {
- LOG(ERROR) << "Could not read COW footer";
- return false;
- }
-
- // Drop the footer from the op stream.
- current_op_num--;
- done = true;
- break;
- } else if (current_op.type == kCowSequenceOp) {
- has_seq_ops_ = true;
- }
- }
-
- // Position for next cluster read
- off_t offs = lseek(fd_.get(), pos, SEEK_SET);
- if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
- PLOG(ERROR) << "lseek next op failed " << offs;
- return false;
- }
- ops_buffer->resize(current_op_num);
- }
-
- LOG(DEBUG) << "COW file read complete. Total ops: " << ops_buffer->size();
- // To successfully parse a COW file, we need either:
- // (1) a label to read up to, and for that label to be found, or
- // (2) a valid footer.
- if (label) {
- if (!last_label_) {
- LOG(ERROR) << "Did not find label " << label.value()
- << " while reading COW (no labels found)";
- return false;
- }
- if (last_label_.value() != label.value()) {
- LOG(ERROR) << "Did not find label " << label.value()
- << ", last label=" << last_label_.value();
- return false;
- }
- } else if (!footer_) {
- LOG(ERROR) << "No COW footer found";
- return false;
- }
-
- uint8_t csum[32];
- memset(csum, 0, sizeof(uint8_t) * 32);
-
- if (footer_) {
- if (ops_buffer->size() != footer_->op.num_ops) {
- LOG(ERROR) << "num ops does not match, expected " << footer_->op.num_ops << ", found "
- << ops_buffer->size();
- return false;
- }
- if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) {
- LOG(ERROR) << "ops size does not match ";
- return false;
- }
- SHA256(&footer_->op, sizeof(footer_->op), footer_->data.footer_checksum);
- if (memcmp(csum, footer_->data.ops_checksum, sizeof(csum)) != 0) {
- LOG(ERROR) << "ops checksum does not match";
- return false;
- }
- SHA256(ops_buffer->data(), footer_->op.ops_size, csum);
- if (memcmp(csum, footer_->data.ops_checksum, sizeof(csum)) != 0) {
- LOG(ERROR) << "ops checksum does not match";
- return false;
- }
- }
-
- ops_ = ops_buffer;
- ops_->shrink_to_fit();
- data_loc_ = data_loc;
-
- return true;
-}
-
//
// This sets up the data needed for MergeOpIter. MergeOpIter presents
// data in the order we intend to merge in.
@@ -430,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;
@@ -445,7 +245,8 @@
continue;
}
- if (!has_seq_ops_ && IsOrderedOp(current_op)) {
+ // Sequence ops must be the first ops in the stream.
+ if (seq_ops_set.empty() && IsOrderedOp(current_op)) {
merge_op_blocks->emplace_back(current_op.new_block);
} else if (seq_ops_set.count(current_op.new_block) == 0) {
other_ops.push_back(current_op.new_block);
@@ -508,47 +309,38 @@
bool CowReader::VerifyMergeOps() {
auto itr = GetMergeOpIter(true);
- std::unordered_map<uint64_t, CowOperation> overwritten_blocks;
- while (!itr->Done()) {
- CowOperation 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 / BLOCK_SZ;
- offset = (op.source % BLOCK_SZ) != 0;
- } else {
+ std::unordered_map<uint64_t, const CowOperation*> overwritten_blocks;
+ while (!itr->AtEnd()) {
+ const auto& op = itr->Get();
+ uint64_t offset;
+ if (!GetSourceOffset(op, &offset)) {
itr->Next();
continue;
}
- CowOperation* overwrite = nullptr;
+ 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];
+ overwrite = overwritten_blocks[block];
LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
<< op << "\noverwritten by previously merged op:\n"
<< *overwrite;
}
- if (offset && overwritten_blocks.count(block + 1)) {
- overwrite = &overwritten_blocks[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"
<< *overwrite;
}
if (overwrite != nullptr) return false;
- overwritten_blocks[op.new_block] = op;
+ overwritten_blocks[op->new_block] = op;
itr->Next();
}
return true;
}
-bool CowReader::GetHeader(CowHeader* header) {
- *header = header_;
- return true;
-}
-
bool CowReader::GetFooter(CowFooter* footer) {
if (!footer_) return false;
*footer = footer_.value();
@@ -565,12 +357,12 @@
public:
CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t start);
- bool Done() override;
- const CowOperation& Get() override;
+ bool AtEnd() override;
+ const CowOperation* Get() override;
void Next() override;
void Prev() override;
- bool RDone() override;
+ bool AtBegin() override;
private:
std::shared_ptr<std::vector<CowOperation>> ops_;
@@ -582,27 +374,27 @@
op_iter_ = ops_->begin() + start;
}
-bool CowOpIter::RDone() {
+bool CowOpIter::AtBegin() {
return op_iter_ == ops_->begin();
}
void CowOpIter::Prev() {
- CHECK(!RDone());
+ CHECK(!AtBegin());
op_iter_--;
}
-bool CowOpIter::Done() {
+bool CowOpIter::AtEnd() {
return op_iter_ == ops_->end();
}
void CowOpIter::Next() {
- CHECK(!Done());
+ CHECK(!AtEnd());
op_iter_++;
}
-const CowOperation& CowOpIter::Get() {
- CHECK(!Done());
- return (*op_iter_);
+const CowOperation* CowOpIter::Get() {
+ CHECK(!AtEnd());
+ return &(*op_iter_);
}
class CowRevMergeOpIter final : public ICowOpIter {
@@ -610,12 +402,12 @@
explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
- bool Done() override;
- const CowOperation& Get() override;
+ bool AtEnd() override;
+ const CowOperation* Get() override;
void Next() override;
void Prev() override;
- bool RDone() override;
+ bool AtBegin() override;
private:
std::shared_ptr<std::vector<CowOperation>> ops_;
@@ -629,12 +421,12 @@
explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
- bool Done() override;
- const CowOperation& Get() override;
+ bool AtEnd() override;
+ const CowOperation* Get() override;
void Next() override;
void Prev() override;
- bool RDone() override;
+ bool AtBegin() override;
private:
std::shared_ptr<std::vector<CowOperation>> ops_;
@@ -651,27 +443,27 @@
block_iter_ = cow_op_index_vec_->begin() + start;
}
-bool CowMergeOpIter::RDone() {
+bool CowMergeOpIter::AtBegin() {
return block_iter_ == cow_op_index_vec_->begin();
}
void CowMergeOpIter::Prev() {
- CHECK(!RDone());
+ CHECK(!AtBegin());
block_iter_--;
}
-bool CowMergeOpIter::Done() {
+bool CowMergeOpIter::AtEnd() {
return block_iter_ == cow_op_index_vec_->end();
}
void CowMergeOpIter::Next() {
- CHECK(!Done());
+ CHECK(!AtEnd());
block_iter_++;
}
-const CowOperation& CowMergeOpIter::Get() {
- CHECK(!Done());
- return ops_->data()[*block_iter_];
+const CowOperation* CowMergeOpIter::Get() {
+ CHECK(!AtEnd());
+ return &ops_->data()[*block_iter_];
}
CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
@@ -683,27 +475,27 @@
block_riter_ = cow_op_index_vec_->rbegin();
}
-bool CowRevMergeOpIter::RDone() {
+bool CowRevMergeOpIter::AtBegin() {
return block_riter_ == cow_op_index_vec_->rbegin();
}
void CowRevMergeOpIter::Prev() {
- CHECK(!RDone());
+ CHECK(!AtBegin());
block_riter_--;
}
-bool CowRevMergeOpIter::Done() {
+bool CowRevMergeOpIter::AtEnd() {
return block_riter_ == cow_op_index_vec_->rend() - start_;
}
void CowRevMergeOpIter::Next() {
- CHECK(!Done());
+ CHECK(!AtEnd());
block_riter_++;
}
-const CowOperation& CowRevMergeOpIter::Get() {
- CHECK(!Done());
- return ops_->data()[*block_riter_];
+const CowOperation* CowRevMergeOpIter::Get() {
+ CHECK(!AtEnd());
+ return &ops_->data()[*block_riter_];
}
std::unique_ptr<ICowOpIter> CowReader::GetOpIter(bool merge_progress) {
@@ -720,10 +512,22 @@
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_.header_size || offset >= fd_size_ - sizeof(CowFooter) || len >= fd_size_ ||
- offset + len > fd_size_ - sizeof(CowFooter)) {
+ if (offset < header_.prefix.header_size || offset >= fd_size_ - sizeof(CowFooter) ||
+ len >= fd_size_ || offset + len > fd_size_ - sizeof(CowFooter)) {
LOG(ERROR) << "invalid data offset: " << offset << ", " << len << " bytes";
return false;
}
@@ -747,18 +551,18 @@
remaining_ = data_length_;
}
- bool Read(void* buffer, size_t length, size_t* read) override {
+ ssize_t Read(void* buffer, size_t length) override {
size_t to_read = std::min(length, remaining_);
if (!to_read) {
- *read = 0;
- return true;
+ return 0;
}
- if (!reader_->GetRawBytes(offset_, buffer, to_read, read)) {
- return false;
+ size_t read;
+ if (!reader_->GetRawBytes(offset_, buffer, to_read, &read)) {
+ return -1;
}
- offset_ += *read;
- remaining_ -= *read;
- return true;
+ offset_ += read;
+ remaining_ -= read;
+ return read;
}
size_t Size() const override { return data_length_; }
@@ -770,11 +574,15 @@
size_t remaining_;
};
-bool CowReader::ReadData(const CowOperation& op, IByteSink* sink) {
+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:
- decompressor = IDecompressor::Uncompressed();
break;
case kCowCompressGz:
decompressor = IDecompressor::Gz();
@@ -782,24 +590,49 @@
case kCowCompressBrotli:
decompressor = IDecompressor::Brotli();
break;
+ case kCowCompressZstd:
+ if (header_.block_size != op->data_length) {
+ decompressor = IDecompressor::Zstd();
+ }
+ break;
case kCowCompressLz4:
- decompressor = IDecompressor::Lz4();
+ if (header_.block_size != op->data_length) {
+ decompressor = IDecompressor::Lz4();
+ }
break;
default:
- LOG(ERROR) << "Unknown compression type: " << op.compression;
- return false;
+ LOG(ERROR) << "Unknown compression type: " << GetCompressionType(op);
+ return -1;
}
uint64_t offset;
- if (op.type == kCowXorOp) {
- offset = data_loc_->at(op.new_block);
+ if (op->type == kCowXorOp) {
+ offset = data_loc_->at(op->new_block);
} else {
- offset = op.source;
+ offset = GetCowOpSourceInfoData(op);
}
- CowDataStream stream(this, offset, op.data_length);
+
+ if (!decompressor) {
+ CowDataStream stream(this, offset + ignore_bytes, op->data_length - ignore_bytes);
+ return stream.ReadFully(buffer, buffer_size);
+ }
+
+ CowDataStream stream(this, offset, op->data_length);
decompressor->set_stream(&stream);
- decompressor->set_sink(sink);
- return decompressor->Decompress(header_.block_size);
+ 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
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
deleted file mode 100644
index 43c17a6..0000000
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
+++ /dev/null
@@ -1,623 +0,0 @@
-//
-// Copyright (C) 2020 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 <sys/types.h>
-#include <unistd.h>
-
-#include <limits>
-#include <queue>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <brotli/encode.h>
-#include <libsnapshot/cow_format.h>
-#include <libsnapshot/cow_reader.h>
-#include <libsnapshot/cow_writer.h>
-#include <lz4.h>
-#include <zlib.h>
-
-#include <fcntl.h>
-#include <linux/fs.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-namespace android {
-namespace snapshot {
-
-namespace {
-std::string GetFdPath(int fd) {
- const auto fd_path = "/proc/self/fd/" + std::to_string(fd);
- std::string file_path(512, '\0');
- const auto err = readlink(fd_path.c_str(), file_path.data(), file_path.size());
- if (err <= 0) {
- PLOG(ERROR) << "Failed to determine path for fd " << fd;
- file_path.clear();
- } else {
- file_path.resize(err);
- }
- return file_path;
-}
-} // namespace
-
-static_assert(sizeof(off_t) == sizeof(uint64_t));
-
-using android::base::borrowed_fd;
-using android::base::unique_fd;
-
-bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
- CHECK(num_blocks != 0);
-
- for (size_t i = 0; i < num_blocks; i++) {
- if (!ValidateNewBlock(new_block + i)) {
- return false;
- }
- }
-
- return EmitCopy(new_block, old_block, num_blocks);
-}
-
-bool ICowWriter::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
- if (size % options_.block_size != 0) {
- LOG(ERROR) << "AddRawBlocks: size " << size << " is not a multiple of "
- << options_.block_size;
- return false;
- }
-
- uint64_t num_blocks = size / options_.block_size;
- uint64_t last_block = new_block_start + num_blocks - 1;
- if (!ValidateNewBlock(last_block)) {
- return false;
- }
- return EmitRawBlocks(new_block_start, data, size);
-}
-
-bool ICowWriter::AddXorBlocks(uint32_t new_block_start, const void* data, size_t size,
- uint32_t old_block, uint16_t offset) {
- if (size % options_.block_size != 0) {
- LOG(ERROR) << "AddRawBlocks: size " << size << " is not a multiple of "
- << options_.block_size;
- return false;
- }
-
- uint64_t num_blocks = size / options_.block_size;
- uint64_t last_block = new_block_start + num_blocks - 1;
- if (!ValidateNewBlock(last_block)) {
- return false;
- }
- if (offset >= options_.block_size) {
- LOG(ERROR) << "AddXorBlocks: offset " << offset << " is not less than "
- << options_.block_size;
- }
- return EmitXorBlocks(new_block_start, data, size, old_block, offset);
-}
-
-bool ICowWriter::AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
- uint64_t last_block = new_block_start + num_blocks - 1;
- if (!ValidateNewBlock(last_block)) {
- return false;
- }
- return EmitZeroBlocks(new_block_start, num_blocks);
-}
-
-bool ICowWriter::AddLabel(uint64_t label) {
- return EmitLabel(label);
-}
-
-bool ICowWriter::AddSequenceData(size_t num_ops, const uint32_t* data) {
- return EmitSequenceData(num_ops, data);
-}
-
-bool ICowWriter::ValidateNewBlock(uint64_t new_block) {
- if (options_.max_blocks && new_block >= options_.max_blocks.value()) {
- LOG(ERROR) << "New block " << new_block << " exceeds maximum block count "
- << options_.max_blocks.value();
- return false;
- }
- return true;
-}
-
-CowWriter::CowWriter(const CowOptions& options) : ICowWriter(options), fd_(-1) {
- SetupHeaders();
-}
-
-void CowWriter::SetupHeaders() {
- header_ = {};
- header_.magic = kCowMagicNumber;
- header_.major_version = kCowVersionMajor;
- header_.minor_version = kCowVersionMinor;
- header_.header_size = sizeof(CowHeader);
- header_.footer_size = sizeof(CowFooter);
- header_.op_size = sizeof(CowOperation);
- header_.block_size = options_.block_size;
- header_.num_merge_ops = options_.num_merge_ops;
- header_.cluster_ops = options_.cluster_ops;
- header_.buffer_size = 0;
- footer_ = {};
- footer_.op.data_length = 64;
- footer_.op.type = kCowFooterOp;
-}
-
-bool CowWriter::ParseOptions() {
- if (options_.compression == "gz") {
- compression_ = kCowCompressGz;
- } else if (options_.compression == "brotli") {
- compression_ = kCowCompressBrotli;
- } else if (options_.compression == "lz4") {
- compression_ = kCowCompressLz4;
- } else if (options_.compression == "none") {
- compression_ = kCowCompressNone;
- } else if (!options_.compression.empty()) {
- LOG(ERROR) << "unrecognized compression: " << options_.compression;
- return false;
- }
- if (options_.cluster_ops == 1) {
- LOG(ERROR) << "Clusters must contain at least two operations to function.";
- return false;
- }
- return true;
-}
-
-bool CowWriter::SetFd(android::base::borrowed_fd fd) {
- if (fd.get() < 0) {
- owned_fd_.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
- if (owned_fd_ < 0) {
- PLOG(ERROR) << "open /dev/null failed";
- return false;
- }
- fd_ = owned_fd_;
- is_dev_null_ = true;
- } else {
- fd_ = fd;
-
- struct stat stat {};
- if (fstat(fd.get(), &stat) < 0) {
- PLOG(ERROR) << "fstat failed";
- return false;
- }
- const auto file_path = GetFdPath(fd.get());
- is_block_device_ = S_ISBLK(stat.st_mode);
- if (is_block_device_) {
- uint64_t size_in_bytes = 0;
- if (ioctl(fd.get(), BLKGETSIZE64, &size_in_bytes)) {
- PLOG(ERROR) << "Failed to get total size for: " << fd.get();
- return false;
- }
- cow_image_size_ = size_in_bytes;
- LOG(INFO) << "COW image " << file_path << " has size " << size_in_bytes;
- } else {
- LOG(INFO) << "COW image " << file_path
- << " is not a block device, assuming unlimited space.";
- }
- }
- return true;
-}
-
-bool CowWriter::Initialize(unique_fd&& fd) {
- owned_fd_ = std::move(fd);
- return Initialize(borrowed_fd{owned_fd_});
-}
-
-bool CowWriter::Initialize(borrowed_fd fd) {
- if (!SetFd(fd) || !ParseOptions()) {
- return false;
- }
-
- return OpenForWrite();
-}
-
-bool CowWriter::InitializeAppend(android::base::unique_fd&& fd, uint64_t label) {
- owned_fd_ = std::move(fd);
- return InitializeAppend(android::base::borrowed_fd{owned_fd_}, label);
-}
-
-bool CowWriter::InitializeAppend(android::base::borrowed_fd fd, uint64_t label) {
- if (!SetFd(fd) || !ParseOptions()) {
- return false;
- }
-
- return OpenForAppend(label);
-}
-
-void CowWriter::InitPos() {
- next_op_pos_ = sizeof(header_) + header_.buffer_size;
- cluster_size_ = header_.cluster_ops * sizeof(CowOperation);
- if (header_.cluster_ops) {
- next_data_pos_ = next_op_pos_ + cluster_size_;
- } else {
- next_data_pos_ = next_op_pos_ + sizeof(CowOperation);
- }
- current_cluster_size_ = 0;
- current_data_size_ = 0;
-}
-
-bool CowWriter::OpenForWrite() {
- // This limitation is tied to the data field size in CowOperation.
- if (header_.block_size > std::numeric_limits<uint16_t>::max()) {
- LOG(ERROR) << "Block size is too large";
- return false;
- }
-
- if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed";
- return false;
- }
-
- if (options_.scratch_space) {
- header_.buffer_size = BUFFER_REGION_DEFAULT_SIZE;
- }
-
- // Headers are not complete, but this ensures the file is at the right
- // position.
- if (!android::base::WriteFully(fd_, &header_, sizeof(header_))) {
- PLOG(ERROR) << "write failed";
- return false;
- }
-
- if (options_.scratch_space) {
- // Initialize the scratch space
- std::string data(header_.buffer_size, 0);
- if (!android::base::WriteFully(fd_, data.data(), header_.buffer_size)) {
- PLOG(ERROR) << "writing scratch space failed";
- return false;
- }
- }
-
- if (!Sync()) {
- LOG(ERROR) << "Header sync failed";
- return false;
- }
-
- if (lseek(fd_.get(), sizeof(header_) + header_.buffer_size, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed";
- return false;
- }
-
- InitPos();
-
- return true;
-}
-
-bool CowWriter::OpenForAppend(uint64_t label) {
- auto reader = std::make_unique<CowReader>();
- std::queue<CowOperation> toAdd;
-
- if (!reader->Parse(fd_, {label}) || !reader->GetHeader(&header_)) {
- return false;
- }
-
- options_.block_size = header_.block_size;
- options_.cluster_ops = header_.cluster_ops;
-
- // Reset this, since we're going to reimport all operations.
- footer_.op.num_ops = 0;
- InitPos();
-
- auto iter = reader->GetOpIter();
-
- while (!iter->Done()) {
- AddOperation(iter->Get());
- iter->Next();
- }
-
- // Free reader so we own the descriptor position again.
- reader = nullptr;
-
- if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed";
- return false;
- }
- return EmitClusterIfNeeded();
-}
-
-bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
- CHECK(!merge_in_progress_);
-
- for (size_t i = 0; i < num_blocks; i++) {
- CowOperation op = {};
- op.type = kCowCopyOp;
- op.new_block = new_block + i;
- op.source = old_block + i;
- if (!WriteOperation(op)) {
- return false;
- }
- }
-
- return true;
-}
-
-bool CowWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
- return EmitBlocks(new_block_start, data, size, 0, 0, kCowReplaceOp);
-}
-
-bool CowWriter::EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
- uint32_t old_block, uint16_t offset) {
- return EmitBlocks(new_block_start, data, size, old_block, offset, kCowXorOp);
-}
-
-bool CowWriter::EmitBlocks(uint64_t new_block_start, const void* data, size_t size,
- uint64_t old_block, uint16_t offset, uint8_t type) {
- const uint8_t* iter = reinterpret_cast<const uint8_t*>(data);
- CHECK(!merge_in_progress_);
- for (size_t i = 0; i < size / header_.block_size; i++) {
- CowOperation op = {};
- op.new_block = new_block_start + i;
- op.type = type;
- if (type == kCowXorOp) {
- op.source = (old_block + i) * header_.block_size + offset;
- } else {
- op.source = next_data_pos_;
- }
-
- if (compression_) {
- auto data = Compress(iter, header_.block_size);
- if (data.empty()) {
- PLOG(ERROR) << "AddRawBlocks: compression failed";
- return false;
- }
- if (data.size() > std::numeric_limits<uint16_t>::max()) {
- LOG(ERROR) << "Compressed block is too large: " << data.size() << " bytes";
- return false;
- }
- op.compression = compression_;
- op.data_length = static_cast<uint16_t>(data.size());
-
- if (!WriteOperation(op, data.data(), data.size())) {
- PLOG(ERROR) << "AddRawBlocks: write failed, bytes requested: " << size
- << ", bytes written: " << i * header_.block_size;
- return false;
- }
- } else {
- op.data_length = static_cast<uint16_t>(header_.block_size);
- if (!WriteOperation(op, iter, header_.block_size)) {
- PLOG(ERROR) << "AddRawBlocks: write failed";
- return false;
- }
- }
-
- iter += header_.block_size;
- }
- return true;
-}
-
-bool CowWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
- CHECK(!merge_in_progress_);
- for (uint64_t i = 0; i < num_blocks; i++) {
- CowOperation op = {};
- op.type = kCowZeroOp;
- op.new_block = new_block_start + i;
- op.source = 0;
- WriteOperation(op);
- }
- return true;
-}
-
-bool CowWriter::EmitLabel(uint64_t label) {
- CHECK(!merge_in_progress_);
- CowOperation op = {};
- op.type = kCowLabelOp;
- op.source = label;
- return WriteOperation(op) && Sync();
-}
-
-bool CowWriter::EmitSequenceData(size_t num_ops, const uint32_t* data) {
- CHECK(!merge_in_progress_);
- size_t to_add = 0;
- size_t max_ops = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t);
- while (num_ops > 0) {
- CowOperation op = {};
- op.type = kCowSequenceOp;
- op.source = next_data_pos_;
- to_add = std::min(num_ops, max_ops);
- op.data_length = static_cast<uint16_t>(to_add * sizeof(uint32_t));
- if (!WriteOperation(op, data, op.data_length)) {
- PLOG(ERROR) << "AddSequenceData: write failed";
- return false;
- }
- num_ops -= to_add;
- data += to_add;
- }
- return true;
-}
-
-bool CowWriter::EmitCluster() {
- CowOperation op = {};
- op.type = kCowClusterOp;
- // Next cluster starts after remainder of current cluster and the next data block.
- op.source = current_data_size_ + cluster_size_ - current_cluster_size_ - sizeof(CowOperation);
- return WriteOperation(op);
-}
-
-bool CowWriter::EmitClusterIfNeeded() {
- // If there isn't room for another op and the cluster end op, end the current cluster
- if (cluster_size_ && cluster_size_ < current_cluster_size_ + 2 * sizeof(CowOperation)) {
- if (!EmitCluster()) return false;
- }
- return true;
-}
-
-// TODO: Fix compilation issues when linking libcrypto library
-// when snapuserd is compiled as part of ramdisk.
-static void SHA256(const void*, size_t, uint8_t[]) {
-#if 0
- SHA256_CTX c;
- SHA256_Init(&c);
- SHA256_Update(&c, data, length);
- SHA256_Final(out, &c);
-#endif
-}
-
-bool CowWriter::Finalize() {
- auto continue_cluster_size = current_cluster_size_;
- auto continue_data_size = current_data_size_;
- auto continue_data_pos = next_data_pos_;
- auto continue_op_pos = next_op_pos_;
- auto continue_num_ops = footer_.op.num_ops;
- bool extra_cluster = false;
-
- // Blank out extra ops, in case we're in append mode and dropped ops.
- if (cluster_size_) {
- auto unused_cluster_space = cluster_size_ - current_cluster_size_;
- std::string clr;
- clr.resize(unused_cluster_space, '\0');
- if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
- PLOG(ERROR) << "Failed to seek to footer position.";
- return false;
- }
- if (!android::base::WriteFully(fd_, clr.data(), clr.size())) {
- PLOG(ERROR) << "clearing unused cluster area failed";
- return false;
- }
- }
-
- // Footer should be at the end of a file, so if there is data after the current block, end it
- // and start a new cluster.
- if (cluster_size_ && current_data_size_ > 0) {
- EmitCluster();
- extra_cluster = true;
- }
-
- footer_.op.ops_size = footer_.op.num_ops * sizeof(CowOperation);
- if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
- PLOG(ERROR) << "Failed to seek to footer position.";
- return false;
- }
- memset(&footer_.data.ops_checksum, 0, sizeof(uint8_t) * 32);
- memset(&footer_.data.footer_checksum, 0, sizeof(uint8_t) * 32);
-
- SHA256(&footer_.op, sizeof(footer_.op), footer_.data.footer_checksum);
- // Write out footer at end of file
- if (!android::base::WriteFully(fd_, reinterpret_cast<const uint8_t*>(&footer_),
- sizeof(footer_))) {
- PLOG(ERROR) << "write footer failed";
- return false;
- }
-
- // Remove excess data, if we're in append mode and threw away more data
- // than we wrote before.
- off_t offs = lseek(fd_.get(), 0, SEEK_CUR);
- if (offs < 0) {
- PLOG(ERROR) << "Failed to lseek to find current position";
- return false;
- }
- if (!Truncate(offs)) {
- return false;
- }
-
- // Reposition for additional Writing
- if (extra_cluster) {
- current_cluster_size_ = continue_cluster_size;
- current_data_size_ = continue_data_size;
- next_data_pos_ = continue_data_pos;
- next_op_pos_ = continue_op_pos;
- footer_.op.num_ops = continue_num_ops;
- }
- return Sync();
-}
-
-uint64_t CowWriter::GetCowSize() {
- if (current_data_size_ > 0) {
- return next_data_pos_ + sizeof(footer_);
- } else {
- return next_op_pos_ + sizeof(footer_);
- }
-}
-
-bool CowWriter::GetDataPos(uint64_t* pos) {
- off_t offs = lseek(fd_.get(), 0, SEEK_CUR);
- if (offs < 0) {
- PLOG(ERROR) << "lseek failed";
- return false;
- }
- *pos = offs;
- return true;
-}
-
-bool CowWriter::EnsureSpaceAvailable(const uint64_t bytes_needed) const {
- if (bytes_needed > cow_image_size_) {
- LOG(ERROR) << "No space left on COW device. Required: " << bytes_needed
- << ", available: " << cow_image_size_;
- errno = ENOSPC;
- return false;
- }
- return true;
-}
-
-bool CowWriter::WriteOperation(const CowOperation& op, const void* data, size_t size) {
- if (!EnsureSpaceAvailable(next_op_pos_ + sizeof(op))) {
- return false;
- }
- if (!EnsureSpaceAvailable(next_data_pos_ + size)) {
- return false;
- }
-
- if (!android::base::WriteFullyAtOffset(fd_, reinterpret_cast<const uint8_t*>(&op), sizeof(op),
- next_op_pos_)) {
- return false;
- }
- if (data != nullptr && size > 0) {
- if (!WriteRawData(data, size)) return false;
- }
- AddOperation(op);
- return EmitClusterIfNeeded();
-}
-
-void CowWriter::AddOperation(const CowOperation& op) {
- footer_.op.num_ops++;
-
- if (op.type == kCowClusterOp) {
- current_cluster_size_ = 0;
- current_data_size_ = 0;
- } else if (header_.cluster_ops) {
- current_cluster_size_ += sizeof(op);
- current_data_size_ += op.data_length;
- }
-
- next_data_pos_ += op.data_length + GetNextDataOffset(op, header_.cluster_ops);
- next_op_pos_ += sizeof(CowOperation) + GetNextOpOffset(op, header_.cluster_ops);
-}
-
-bool CowWriter::WriteRawData(const void* data, const size_t size) {
- if (!android::base::WriteFullyAtOffset(fd_, data, size, next_data_pos_)) {
- return false;
- }
- return true;
-}
-
-bool CowWriter::Sync() {
- if (is_dev_null_) {
- return true;
- }
- if (fsync(fd_.get()) < 0) {
- PLOG(ERROR) << "fsync failed";
- return false;
- }
- return true;
-}
-
-bool CowWriter::Truncate(off_t length) {
- if (is_dev_null_ || is_block_device_) {
- return true;
- }
- if (ftruncate(fd_.get(), length) < 0) {
- PLOG(ERROR) << "Failed to truncate.";
- return false;
- }
- return true;
-}
-
-} // 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 167ff8c..a6dee4f 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <unistd.h>
+#include <chrono>
#include <iomanip>
#include <iostream>
#include <string>
@@ -23,11 +24,26 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
+#include <gflags/gflags.h>
#include <libsnapshot/cow_reader.h>
+#include "parser_v2.h"
+
+DEFINE_bool(silent, false, "Run silently");
+DEFINE_bool(decompress, false, "Attempt to decompress data ops");
+DEFINE_bool(show_bad_data, false, "If an op fails to decompress, show its daw data");
+DEFINE_bool(show_ops, false, "Print all opcode information");
+DEFINE_string(order, "", "If show_ops is true, change the order (either merge or reverse-merge)");
+DEFINE_bool(show_merged, false,
+ "If show_ops is true, and order is merge or reverse-merge, include merged ops");
+DEFINE_bool(verify_merge_sequence, false, "Verify merge order sequencing");
+DEFINE_bool(show_merge_sequence, false, "Show merge order sequence");
+DEFINE_bool(show_raw_ops, false, "Show raw ops directly from the underlying parser");
namespace android {
namespace snapshot {
+using android::base::borrowed_fd;
+
void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
unsigned int, const char* message) {
if (severity == android::base::ERROR) {
@@ -37,69 +53,57 @@
}
}
-static void usage(void) {
- LOG(ERROR) << "Usage: inspect_cow [-sd] <COW_FILE>";
- LOG(ERROR) << "\t -s Run Silent";
- LOG(ERROR) << "\t -d Attempt to decompress";
- LOG(ERROR) << "\t -b Show data for failed decompress";
- LOG(ERROR) << "\t -l Show ops";
- LOG(ERROR) << "\t -m Show ops in reverse merge order";
- LOG(ERROR) << "\t -n Show ops in merge order";
- LOG(ERROR) << "\t -a Include merged ops in any merge order listing";
- LOG(ERROR) << "\t -o Shows sequence op block order";
- LOG(ERROR) << "\t -v Verifies merge order has no conflicts\n";
-}
-
-enum OpIter { Normal, RevMerge, Merge };
-
-struct Options {
- bool silent;
- bool decompress;
- bool show_ops;
- bool show_bad;
- bool show_seq;
- bool verify_sequence;
- OpIter iter_type;
- bool include_merged;
-};
-
-// Sink that always appends to the end of a string.
-class StringSink : public IByteSink {
- public:
- void* GetBuffer(size_t requested, size_t* actual) override {
- size_t old_size = stream_.size();
- stream_.resize(old_size + requested, '\0');
- *actual = requested;
- return stream_.data() + old_size;
- }
- bool ReturnData(void*, size_t) override { return true; }
- void Reset() { stream_.clear(); }
-
- std::string& stream() { return stream_; }
-
- private:
- std::string stream_;
-};
-
-static void ShowBad(CowReader& reader, const struct CowOperation& op) {
+static void ShowBad(CowReader& reader, const struct CowOperation* op) {
size_t count;
- auto buffer = std::make_unique<uint8_t[]>(op.data_length);
+ 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";
- for (int i = 0; i < op.data_length; i++) {
+ for (int i = 0; i < op->data_length; i++) {
std::cout << std::hex << (int)buffer[i];
}
std::cout << std::dec << "\n\n";
- if (op.data_length >= sizeof(CowOperation)) {
+ if (op->data_length >= sizeof(CowOperation)) {
std::cout << "The start, as an op, would be " << *(CowOperation*)buffer.get() << "\n";
}
}
}
-static bool Inspect(const std::string& path, Options opt) {
+static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) {
+ CowParserV2 parser;
+ if (!parser.Parse(fd, header)) {
+ LOG(ERROR) << "v2 parser failed";
+ return false;
+ }
+ for (const auto& op : *parser.ops()) {
+ std::cout << op << "\n";
+ if (auto iter = parser.data_loc()->find(op.new_block); iter != parser.data_loc()->end()) {
+ std::cout << " data loc: " << iter->second << "\n";
+ }
+ }
+ return true;
+}
+
+static bool ShowRawOpStream(borrowed_fd fd) {
+ CowHeader header;
+ if (!ReadCowHeader(fd, &header)) {
+ LOG(ERROR) << "parse header failed";
+ return false;
+ }
+
+ switch (header.prefix.major_version) {
+ case 1:
+ case 2:
+ return ShowRawOpStreamV2(fd, header);
+ default:
+ LOG(ERROR) << "unknown COW version: " << header.prefix.major_version;
+ return false;
+ }
+}
+
+static bool Inspect(const std::string& path) {
android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
if (fd < 0) {
PLOG(ERROR) << "open failed: " << path;
@@ -107,37 +111,41 @@
}
CowReader reader;
+
+ auto start_time = std::chrono::steady_clock::now();
if (!reader.Parse(fd)) {
LOG(ERROR) << "parse failed: " << path;
return false;
}
+ std::chrono::duration<double> parse_time = std::chrono::steady_clock::now() - start_time;
- CowHeader header;
- if (!reader.GetHeader(&header)) {
- LOG(ERROR) << "could not get header: " << path;
- return false;
- }
+ const CowHeader& header = reader.GetHeader();
CowFooter footer;
bool has_footer = false;
if (reader.GetFooter(&footer)) has_footer = true;
- if (!opt.silent) {
- std::cout << "Major version: " << header.major_version << "\n";
- std::cout << "Minor version: " << header.minor_version << "\n";
- std::cout << "Header size: " << header.header_size << "\n";
+ if (!FLAGS_silent) {
+ std::cout << "Version: " << header.prefix.major_version << "."
+ << header.prefix.minor_version << "\n";
+ std::cout << "Header size: " << header.prefix.header_size << "\n";
std::cout << "Footer size: " << header.footer_size << "\n";
std::cout << "Block size: " << header.block_size << "\n";
- std::cout << "Num merge ops: " << header.num_merge_ops << "\n";
- std::cout << "RA buffer size: " << header.buffer_size << "\n";
- std::cout << "\n";
+ std::cout << "Merge ops: " << header.num_merge_ops << "\n";
+ std::cout << "Readahead buffer: " << header.buffer_size << " bytes\n";
if (has_footer) {
- std::cout << "Total Ops size: " << footer.op.ops_size << "\n";
- std::cout << "Number of Ops: " << footer.op.num_ops << "\n";
- std::cout << "\n";
+ std::cout << "Footer: ops usage: " << footer.op.ops_size << " bytes\n";
+ std::cout << "Footer: op count: " << footer.op.num_ops << "\n";
+ } else {
+ std::cout << "Footer: none\n";
}
}
- if (opt.verify_sequence) {
+ if (!FLAGS_silent) {
+ std::cout << "Parse time: " << (parse_time.count() * 1000) << "ms\n";
+ }
+
+ if (FLAGS_verify_merge_sequence) {
+ std::cout << "\n";
if (reader.VerifyMergeOps()) {
std::cout << "\nMerge sequence is consistent.\n";
} else {
@@ -146,41 +154,57 @@
}
std::unique_ptr<ICowOpIter> iter;
- if (opt.iter_type == Normal) {
+ if (FLAGS_order.empty()) {
iter = reader.GetOpIter();
- } else if (opt.iter_type == RevMerge) {
- iter = reader.GetRevMergeOpIter(opt.include_merged);
- } else if (opt.iter_type == Merge) {
- iter = reader.GetMergeOpIter(opt.include_merged);
+ } else if (FLAGS_order == "reverse-merge") {
+ iter = reader.GetRevMergeOpIter(FLAGS_show_merged);
+ } else if (FLAGS_order == "merge") {
+ iter = reader.GetMergeOpIter(FLAGS_show_merged);
}
- StringSink sink;
+
+ std::string buffer(header.block_size, '\0');
+
+ if (!FLAGS_silent && FLAGS_show_raw_ops) {
+ std::cout << "\n";
+ std::cout << "Listing raw op stream:\n";
+ std::cout << "----------------------\n";
+ if (!ShowRawOpStream(fd)) {
+ return false;
+ }
+ }
+
+ if (!FLAGS_silent && FLAGS_show_ops) {
+ std::cout << "\n";
+ std::cout << "Listing op stream:\n";
+ std::cout << "------------------\n";
+ }
+
bool success = true;
uint64_t xor_ops = 0, copy_ops = 0, replace_ops = 0, zero_ops = 0;
- while (!iter->Done()) {
- const CowOperation& op = iter->Get();
+ while (!iter->AtEnd()) {
+ const CowOperation* op = iter->Get();
- if (!opt.silent && opt.show_ops) std::cout << op << "\n";
+ if (!FLAGS_silent && FLAGS_show_ops) std::cout << *op << "\n";
- if (opt.decompress && op.type == kCowReplaceOp && op.compression != kCowCompressNone) {
- if (!reader.ReadData(op, &sink)) {
- std::cerr << "Failed to decompress for :" << op << "\n";
+ if (FLAGS_decompress && op->type == kCowReplaceOp && op->compression != kCowCompressNone) {
+ if (reader.ReadData(op, buffer.data(), buffer.size()) < 0) {
+ std::cerr << "Failed to decompress for :" << *op << "\n";
success = false;
- if (opt.show_bad) ShowBad(reader, op);
+ if (FLAGS_show_bad_data) ShowBad(reader, op);
}
- sink.Reset();
}
- if (op.type == kCowSequenceOp && opt.show_seq) {
+ if (op->type == kCowSequenceOp && FLAGS_show_merge_sequence) {
size_t read;
std::vector<uint32_t> merge_op_blocks;
- size_t seq_len = op.data_length / sizeof(uint32_t);
+ 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;
}
- if (!opt.silent) {
- std::cout << "Sequence for " << op << " is :\n";
+ if (!FLAGS_silent) {
+ std::cout << "Sequence for " << *op << " is :\n";
for (size_t i = 0; i < seq_len; i++) {
std::cout << std::setfill('0') << std::setw(6) << merge_op_blocks[i] << ", ";
if ((i + 1) % 10 == 0 || i + 1 == seq_len) std::cout << "\n";
@@ -188,24 +212,26 @@
}
}
- if (op.type == kCowCopyOp) {
+ if (op->type == kCowCopyOp) {
copy_ops++;
- } else if (op.type == kCowReplaceOp) {
+ } else if (op->type == kCowReplaceOp) {
replace_ops++;
- } else if (op.type == kCowZeroOp) {
+ } else if (op->type == kCowZeroOp) {
zero_ops++;
- } else if (op.type == kCowXorOp) {
+ } else if (op->type == kCowXorOp) {
xor_ops++;
}
iter->Next();
}
- if (!opt.silent) {
+ if (!FLAGS_silent) {
auto total_ops = replace_ops + zero_ops + copy_ops + xor_ops;
- std::cout << "Total-data-ops: " << total_ops << "Replace-ops: " << replace_ops
- << " Zero-ops: " << zero_ops << " Copy-ops: " << copy_ops
- << " Xor_ops: " << xor_ops << std::endl;
+ std::cout << "Data ops: " << total_ops << "\n";
+ std::cout << "Replace ops: " << replace_ops << "\n";
+ std::cout << "Zero ops: " << zero_ops << "\n";
+ std::cout << "Copy ops: " << copy_ops << "\n";
+ std::cout << "Xor ops: " << xor_ops << "\n";
}
return success;
@@ -215,55 +241,20 @@
} // namespace android
int main(int argc, char** argv) {
- int ch;
- struct android::snapshot::Options opt;
- opt.silent = false;
- opt.decompress = false;
- opt.show_bad = false;
- opt.iter_type = android::snapshot::Normal;
- opt.verify_sequence = false;
- opt.include_merged = false;
- while ((ch = getopt(argc, argv, "sdbmnolva")) != -1) {
- switch (ch) {
- case 's':
- opt.silent = true;
- break;
- case 'd':
- opt.decompress = true;
- break;
- case 'b':
- opt.show_bad = true;
- break;
- case 'm':
- opt.iter_type = android::snapshot::RevMerge;
- break;
- case 'n':
- opt.iter_type = android::snapshot::Merge;
- break;
- case 'o':
- opt.show_seq = true;
- break;
- case 'l':
- opt.show_ops = true;
- break;
- case 'v':
- opt.verify_sequence = true;
- break;
- case 'a':
- opt.include_merged = true;
- break;
- default:
- android::snapshot::usage();
- }
- }
- android::base::InitLogging(argv, android::snapshot::MyLogger);
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
- if (argc < optind + 1) {
- android::snapshot::usage();
+ if (argc < 2) {
+ gflags::ShowUsageWithFlags(argv[0]);
+ return 1;
+ }
+ if (FLAGS_order != "" && FLAGS_order != "merge" && FLAGS_order != "reverse-merge") {
+ std::cerr << "Order must either be \"merge\" or \"reverse-merge\".\n";
return 1;
}
- if (!android::snapshot::Inspect(argv[optind], opt)) {
+ android::base::InitLogging(argv, android::snapshot::MyLogger);
+
+ if (!android::snapshot::Inspect(argv[1])) {
return 1;
}
return 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v2.cpp
new file mode 100644
index 0000000..fdb5c59
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v2.cpp
@@ -0,0 +1,238 @@
+// 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 "parser_v2.h"
+
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+
+namespace android {
+namespace snapshot {
+
+using android::base::borrowed_fd;
+
+bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) {
+ if (lseek(fd.get(), 0, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek header failed";
+ return false;
+ }
+
+ memset(header, 0, sizeof(*header));
+
+ if (!android::base::ReadFully(fd, &header->prefix, sizeof(header->prefix))) {
+ return false;
+ }
+ if (header->prefix.magic != kCowMagicNumber) {
+ LOG(ERROR) << "Header Magic corrupted. Magic: " << header->prefix.magic
+ << "Expected: " << kCowMagicNumber;
+ return false;
+ }
+ if (header->prefix.header_size > sizeof(CowHeader)) {
+ LOG(ERROR) << "Unknown CowHeader size (got " << header->prefix.header_size
+ << " bytes, expected at most " << sizeof(CowHeader) << " bytes)";
+ return false;
+ }
+
+ if (lseek(fd.get(), 0, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek header failed";
+ return false;
+ }
+ return android::base::ReadFully(fd, header, header->prefix.header_size);
+}
+
+bool CowParserV2::Parse(borrowed_fd fd, const CowHeader& header, std::optional<uint64_t> label) {
+ auto pos = lseek(fd.get(), 0, SEEK_END);
+ if (pos < 0) {
+ PLOG(ERROR) << "lseek end failed";
+ return false;
+ }
+ fd_size_ = pos;
+ header_ = header;
+
+ if (header_.footer_size != sizeof(CowFooter)) {
+ LOG(ERROR) << "Footer size unknown, read " << header_.footer_size << ", expected "
+ << sizeof(CowFooter);
+ return false;
+ }
+ if (header_.op_size != sizeof(CowOperation)) {
+ LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
+ << sizeof(CowOperation);
+ return false;
+ }
+ if (header_.cluster_ops == 1) {
+ LOG(ERROR) << "Clusters must contain at least two operations to function.";
+ return false;
+ }
+ if (header_.op_size != sizeof(CowOperation)) {
+ LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
+ << sizeof(CowOperation);
+ return false;
+ }
+ if (header_.cluster_ops == 1) {
+ LOG(ERROR) << "Clusters must contain at least two operations to function.";
+ return false;
+ }
+
+ if ((header_.prefix.major_version > kCowVersionMajor) ||
+ (header_.prefix.minor_version != kCowVersionMinor)) {
+ LOG(ERROR) << "Header version mismatch, "
+ << "major version: " << header_.prefix.major_version
+ << ", expected: " << kCowVersionMajor
+ << ", minor version: " << header_.prefix.minor_version
+ << ", expected: " << kCowVersionMinor;
+ return false;
+ }
+
+ return ParseOps(fd, label);
+}
+
+bool CowParserV2::ParseOps(borrowed_fd fd, std::optional<uint64_t> label) {
+ uint64_t pos;
+ auto data_loc = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
+
+ // Skip the scratch space
+ if (header_.prefix.major_version >= 2 && (header_.buffer_size > 0)) {
+ LOG(DEBUG) << " Scratch space found of size: " << header_.buffer_size;
+ size_t init_offset = header_.prefix.header_size + header_.buffer_size;
+ pos = lseek(fd.get(), init_offset, SEEK_SET);
+ if (pos != init_offset) {
+ PLOG(ERROR) << "lseek ops failed";
+ return false;
+ }
+ } else {
+ pos = lseek(fd.get(), header_.prefix.header_size, SEEK_SET);
+ if (pos != header_.prefix.header_size) {
+ PLOG(ERROR) << "lseek ops failed";
+ return false;
+ }
+ // Reading a v1 version of COW which doesn't have buffer_size.
+ header_.buffer_size = 0;
+ }
+ uint64_t data_pos = 0;
+
+ if (header_.cluster_ops) {
+ data_pos = pos + header_.cluster_ops * sizeof(CowOperation);
+ } else {
+ data_pos = pos + sizeof(CowOperation);
+ }
+
+ auto ops_buffer = std::make_shared<std::vector<CowOperation>>();
+ uint64_t current_op_num = 0;
+ uint64_t cluster_ops = header_.cluster_ops ?: 1;
+ bool done = false;
+
+ // Alternating op clusters and data
+ while (!done) {
+ uint64_t to_add = std::min(cluster_ops, (fd_size_ - pos) / sizeof(CowOperation));
+ if (to_add == 0) break;
+ ops_buffer->resize(current_op_num + to_add);
+ if (!android::base::ReadFully(fd, &ops_buffer->data()[current_op_num],
+ to_add * sizeof(CowOperation))) {
+ PLOG(ERROR) << "read op failed";
+ return false;
+ }
+ // Parse current cluster to find start of next cluster
+ while (current_op_num < ops_buffer->size()) {
+ auto& current_op = ops_buffer->data()[current_op_num];
+ current_op_num++;
+ if (current_op.type == kCowXorOp) {
+ data_loc->insert({current_op.new_block, data_pos});
+ }
+ pos += sizeof(CowOperation) + GetNextOpOffset(current_op, header_.cluster_ops);
+ data_pos += current_op.data_length + GetNextDataOffset(current_op, header_.cluster_ops);
+
+ if (current_op.type == kCowClusterOp) {
+ break;
+ } else if (current_op.type == kCowLabelOp) {
+ last_label_ = {current_op.source};
+
+ // If we reach the requested label, stop reading.
+ if (label && label.value() == current_op.source) {
+ done = true;
+ break;
+ }
+ } else if (current_op.type == kCowFooterOp) {
+ footer_.emplace();
+ CowFooter* footer = &footer_.value();
+ memcpy(&footer_->op, ¤t_op, sizeof(footer->op));
+ off_t offs = lseek(fd.get(), pos, SEEK_SET);
+ if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
+ PLOG(ERROR) << "lseek next op failed " << offs;
+ return false;
+ }
+ if (!android::base::ReadFully(fd, &footer->unused, sizeof(footer->unused))) {
+ LOG(ERROR) << "Could not read COW footer";
+ return false;
+ }
+
+ // Drop the footer from the op stream.
+ current_op_num--;
+ done = true;
+ break;
+ }
+ }
+
+ // Position for next cluster read
+ off_t offs = lseek(fd.get(), pos, SEEK_SET);
+ if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
+ PLOG(ERROR) << "lseek next op failed " << offs;
+ return false;
+ }
+ ops_buffer->resize(current_op_num);
+ }
+
+ LOG(DEBUG) << "COW file read complete. Total ops: " << ops_buffer->size();
+ // To successfully parse a COW file, we need either:
+ // (1) a label to read up to, and for that label to be found, or
+ // (2) a valid footer.
+ if (label) {
+ if (!last_label_) {
+ LOG(ERROR) << "Did not find label " << label.value()
+ << " while reading COW (no labels found)";
+ return false;
+ }
+ if (last_label_.value() != label.value()) {
+ LOG(ERROR) << "Did not find label " << label.value()
+ << ", last label=" << last_label_.value();
+ return false;
+ }
+ } else if (!footer_) {
+ LOG(ERROR) << "No COW footer found";
+ return false;
+ }
+
+ uint8_t csum[32];
+ memset(csum, 0, sizeof(uint8_t) * 32);
+
+ if (footer_) {
+ if (ops_buffer->size() != footer_->op.num_ops) {
+ LOG(ERROR) << "num ops does not match, expected " << footer_->op.num_ops << ", found "
+ << ops_buffer->size();
+ return false;
+ }
+ if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) {
+ LOG(ERROR) << "ops size does not match ";
+ return false;
+ }
+ }
+
+ ops_ = ops_buffer;
+ ops_->shrink_to_fit();
+ data_loc_ = data_loc;
+ return true;
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v2.h b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v2.h
new file mode 100644
index 0000000..afcf687
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v2.h
@@ -0,0 +1,55 @@
+// 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 <stdint.h>
+
+#include <memory>
+#include <optional>
+#include <unordered_map>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+#include <libsnapshot/cow_format.h>
+
+namespace android {
+namespace snapshot {
+
+class CowParserV2 {
+ public:
+ bool Parse(android::base::borrowed_fd fd, const CowHeader& header,
+ std::optional<uint64_t> label = {});
+
+ const CowHeader& header() const { return header_; }
+ const std::optional<CowFooter>& footer() const { return footer_; }
+ std::shared_ptr<std::vector<CowOperation>> ops() { return ops_; }
+ std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc() const { return data_loc_; }
+ uint64_t fd_size() const { return fd_size_; }
+ const std::optional<uint64_t>& last_label() const { return last_label_; }
+
+ private:
+ bool ParseOps(android::base::borrowed_fd fd, std::optional<uint64_t> label);
+
+ CowHeader header_ = {};
+ std::optional<CowFooter> footer_;
+ std::shared_ptr<std::vector<CowOperation>> ops_;
+ std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_;
+ uint64_t fd_size_;
+ std::optional<uint64_t> last_label_;
+};
+
+bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header);
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
new file mode 100644
index 0000000..a3e40d9
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
@@ -0,0 +1,262 @@
+//
+// Copyright (C) 2020 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 "snapshot_reader.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+
+namespace android {
+namespace snapshot {
+
+using android::base::borrowed_fd;
+
+CompressedSnapshotReader::CompressedSnapshotReader(std::unique_ptr<ICowReader>&& cow,
+ const std::optional<std::string>& source_device,
+ std::optional<uint64_t> block_dev_size)
+ : cow_(std::move(cow)),
+ block_size_(cow_->GetHeader().block_size),
+ source_device_(source_device),
+ block_device_size_(block_dev_size.value_or(0)) {
+ const auto& header = cow_->GetHeader();
+ block_size_ = header.block_size;
+
+ // Populate the operation map.
+ op_iter_ = cow_->GetOpIter(false);
+ while (!op_iter_->AtEnd()) {
+ const CowOperation* op = op_iter_->Get();
+ if (IsMetadataOp(*op)) {
+ op_iter_->Next();
+ continue;
+ }
+ if (op->new_block >= ops_.size()) {
+ ops_.resize(op->new_block + 1, nullptr);
+ }
+ ops_[op->new_block] = op;
+ op_iter_->Next();
+ }
+}
+
+// Not supported.
+bool CompressedSnapshotReader::Open(const char*, int, mode_t) {
+ errno = EINVAL;
+ return false;
+}
+
+bool CompressedSnapshotReader::Open(const char*, int) {
+ errno = EINVAL;
+ return false;
+}
+
+ssize_t CompressedSnapshotReader::Write(const void*, size_t) {
+ errno = EINVAL;
+ return false;
+}
+
+bool CompressedSnapshotReader::BlkIoctl(int, uint64_t, uint64_t, int*) {
+ errno = EINVAL;
+ return false;
+}
+
+borrowed_fd CompressedSnapshotReader::GetSourceFd() {
+ if (source_fd_ < 0) {
+ if (!source_device_) {
+ LOG(ERROR) << "CompressedSnapshotReader needs source device, but none was set";
+ errno = EINVAL;
+ return {-1};
+ }
+ source_fd_.reset(open(source_device_->c_str(), O_RDONLY | O_CLOEXEC));
+ if (source_fd_ < 0) {
+ PLOG(ERROR) << "open " << *source_device_;
+ return {-1};
+ }
+ }
+ return source_fd_;
+}
+
+ssize_t CompressedSnapshotReader::Read(void* buf, size_t count) {
+ // Find the start and end chunks, inclusive.
+ uint64_t start_chunk = offset_ / block_size_;
+ uint64_t end_chunk = (offset_ + count - 1) / block_size_;
+
+ // Chop off the first N bytes if the position is not block-aligned.
+ size_t start_offset = offset_ % block_size_;
+
+ uint8_t* buf_pos = reinterpret_cast<uint8_t*>(buf);
+ size_t buf_remaining = count;
+
+ size_t initial_bytes = std::min(block_size_ - start_offset, buf_remaining);
+ ssize_t rv = ReadBlock(start_chunk, start_offset, buf_pos, initial_bytes);
+ if (rv < 0) {
+ return -1;
+ }
+ offset_ += rv;
+ buf_pos += rv;
+ buf_remaining -= rv;
+
+ for (uint64_t chunk = start_chunk + 1; chunk < end_chunk; chunk++) {
+ ssize_t rv = ReadBlock(chunk, 0, buf_pos, buf_remaining);
+ if (rv < 0) {
+ return -1;
+ }
+ offset_ += rv;
+ buf_pos += rv;
+ buf_remaining -= rv;
+ }
+
+ if (buf_remaining) {
+ ssize_t rv = ReadBlock(end_chunk, 0, buf_pos, buf_remaining);
+ if (rv < 0) {
+ return -1;
+ }
+ offset_ += rv;
+ buf_pos += rv;
+ buf_remaining -= rv;
+ }
+
+ CHECK_EQ(buf_pos - reinterpret_cast<uint8_t*>(buf), count);
+ CHECK_EQ(buf_remaining, 0);
+
+ errno = 0;
+ return count;
+}
+
+ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, size_t start_offset, void* buffer,
+ size_t buffer_size) {
+ size_t bytes_to_read = std::min(static_cast<size_t>(block_size_), buffer_size);
+
+ // The offset is relative to the chunk; we should be reading no more than
+ // one chunk.
+ CHECK(start_offset + bytes_to_read <= block_size_);
+
+ const CowOperation* op = nullptr;
+ if (chunk < ops_.size()) {
+ op = ops_[chunk];
+ }
+
+ if (!op || op->type == kCowCopyOp) {
+ borrowed_fd fd = GetSourceFd();
+ if (fd < 0) {
+ // GetSourceFd sets errno.
+ return -1;
+ }
+
+ if (op) {
+ 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;
+ if (!android::base::ReadFullyAtOffset(fd, buffer, bytes_to_read, offset)) {
+ PLOG(ERROR) << "read " << *source_device_;
+ // ReadFullyAtOffset sets errno.
+ return -1;
+ }
+ } else if (op->type == kCowZeroOp) {
+ memset(buffer, 0, bytes_to_read);
+ } else if (op->type == kCowReplaceOp) {
+ if (cow_->ReadData(op, buffer, bytes_to_read, start_offset) < bytes_to_read) {
+ LOG(ERROR) << "CompressedSnapshotReader failed to read replace op";
+ errno = EIO;
+ return -1;
+ }
+ } else if (op->type == kCowXorOp) {
+ borrowed_fd fd = GetSourceFd();
+ if (fd < 0) {
+ // GetSourceFd sets errno.
+ return -1;
+ }
+
+ 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)) {
+ PLOG(ERROR) << "read " << *source_device_;
+ // ReadFullyAtOffset sets errno.
+ return -1;
+ }
+
+ if (cow_->ReadData(op, buffer, bytes_to_read, start_offset) < bytes_to_read) {
+ LOG(ERROR) << "CompressedSnapshotReader failed to read xor op";
+ errno = EIO;
+ return -1;
+ }
+
+ for (size_t i = 0; i < bytes_to_read; i++) {
+ ((char*)buffer)[i] ^= data[i];
+ }
+ } else {
+ LOG(ERROR) << "CompressedSnapshotReader unknown op type: " << uint32_t(op->type);
+ errno = EINVAL;
+ return -1;
+ }
+
+ // MemoryByteSink doesn't do anything in ReturnBuffer, so don't bother calling it.
+ return bytes_to_read;
+}
+
+off64_t CompressedSnapshotReader::Seek(off64_t offset, int whence) {
+ switch (whence) {
+ case SEEK_SET:
+ offset_ = offset;
+ break;
+ case SEEK_END:
+ offset_ = static_cast<off64_t>(block_device_size_) + offset;
+ break;
+ case SEEK_CUR:
+ offset_ += offset;
+ break;
+ default:
+ LOG(ERROR) << "Unrecognized seek whence: " << whence;
+ errno = EINVAL;
+ return -1;
+ }
+ return offset_;
+}
+
+uint64_t CompressedSnapshotReader::BlockDevSize() {
+ return block_device_size_;
+}
+
+bool CompressedSnapshotReader::Close() {
+ cow_ = nullptr;
+ source_fd_ = {};
+ return true;
+}
+
+bool CompressedSnapshotReader::IsSettingErrno() {
+ return true;
+}
+
+bool CompressedSnapshotReader::IsOpen() {
+ return cow_ != nullptr;
+}
+
+bool CompressedSnapshotReader::Flush() {
+ return true;
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_reader.h b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.h
similarity index 64%
rename from fs_mgr/libsnapshot/snapshot_reader.h
rename to fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.h
index a3e7e22..3de63ed 100644
--- a/fs_mgr/libsnapshot/snapshot_reader.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.h
@@ -26,18 +26,16 @@
namespace android {
namespace snapshot {
-class ReadOnlyFileDescriptor : public chromeos_update_engine::FileDescriptor {
+class CompressedSnapshotReader : public chromeos_update_engine::FileDescriptor {
public:
+ CompressedSnapshotReader(std::unique_ptr<ICowReader>&& cow,
+ const std::optional<std::string>& source_device,
+ std::optional<uint64_t> block_dev_size);
+
bool Open(const char* path, int flags, mode_t mode) override;
bool Open(const char* path, int flags) override;
ssize_t Write(const void* buf, size_t count) override;
bool BlkIoctl(int request, uint64_t start, uint64_t length, int* result) override;
-};
-
-class ReadFdFileDescriptor : public ReadOnlyFileDescriptor {
- public:
- explicit ReadFdFileDescriptor(android::base::unique_fd&& fd);
-
ssize_t Read(void* buf, size_t count) override;
off64_t Seek(off64_t offset, int whence) override;
uint64_t BlockDevSize() override;
@@ -47,29 +45,10 @@
bool Flush() override;
private:
- android::base::unique_fd fd_;
-};
-
-class CompressedSnapshotReader : public ReadOnlyFileDescriptor {
- public:
- bool SetCow(std::unique_ptr<CowReader>&& cow);
- void SetSourceDevice(const std::string& source_device);
- void SetBlockDeviceSize(uint64_t block_device_size);
-
- ssize_t Read(void* buf, size_t count) override;
- off64_t Seek(off64_t offset, int whence) override;
- uint64_t BlockDevSize() override;
- bool Close() override;
- bool IsSettingErrno() override;
- bool IsOpen() override;
- bool Flush() override;
-
- private:
- ssize_t ReadBlock(uint64_t chunk, IByteSink* sink, size_t start_offset,
- const std::optional<uint64_t>& max_bytes = {});
+ ssize_t ReadBlock(uint64_t chunk, size_t start_offset, void* buffer, size_t size);
android::base::borrowed_fd GetSourceFd();
- std::unique_ptr<CowReader> cow_;
+ std::unique_ptr<ICowReader> cow_;
std::unique_ptr<ICowOpIter> op_iter_;
uint32_t block_size_ = 0;
diff --git a/fs_mgr/libsnapshot/snapshot_reader_test.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp
similarity index 88%
rename from fs_mgr/libsnapshot/snapshot_reader_test.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp
index 9adc655..10cb06d 100644
--- a/fs_mgr/libsnapshot/snapshot_reader_test.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <libsnapshot/snapshot.h>
-
#include <unordered_set>
#include <android-base/file.h>
@@ -61,7 +59,7 @@
ASSERT_EQ(fsync(base_->fd), 0);
}
- void WriteCow(ISnapshotWriter* writer) {
+ void WriteCow(ICowWriter* writer) {
std::string new_block = MakeNewBlockString();
std::string xor_block = MakeXorBlockString();
@@ -72,8 +70,8 @@
ASSERT_TRUE(writer->Finalize());
}
- void TestBlockReads(ISnapshotWriter* writer) {
- auto reader = writer->OpenReader();
+ void TestBlockReads(ICowWriter* writer) {
+ auto reader = writer->OpenFileDescriptor(base_->path);
ASSERT_NE(reader, nullptr);
// Test that unchanged blocks are not modified.
@@ -117,8 +115,8 @@
ASSERT_EQ(two_blocks, zeroes);
}
- void TestByteReads(ISnapshotWriter* writer) {
- auto reader = writer->OpenReader();
+ void TestByteReads(ICowWriter* writer) {
+ auto reader = writer->OpenFileDescriptor(base_->path);
ASSERT_NE(reader, nullptr);
std::string blob(kBlockSize * 3, 'x');
@@ -140,9 +138,21 @@
ASSERT_EQ(reader->Seek(offset, SEEK_SET), offset);
ASSERT_EQ(reader->Read(&value, sizeof(value)), sizeof(value));
ASSERT_EQ(value, MakeNewBlockString()[1000]);
+
+ // Test a sequence of one byte reads.
+ offset = 5 * kBlockSize + 10;
+ std::string expected = MakeNewBlockString().substr(10, 20);
+ ASSERT_EQ(reader->Seek(offset, SEEK_SET), offset);
+
+ std::string got;
+ while (got.size() < expected.size()) {
+ ASSERT_EQ(reader->Read(&value, sizeof(value)), sizeof(value));
+ got.push_back(value);
+ }
+ ASSERT_EQ(got, expected);
}
- void TestReads(ISnapshotWriter* writer) {
+ void TestReads(ICowWriter* writer) {
ASSERT_NO_FATAL_FAILURE(TestBlockReads(writer));
ASSERT_NO_FATAL_FAILURE(TestByteReads(writer));
}
@@ -174,10 +184,7 @@
unique_fd cow_fd(dup(cow_->fd));
ASSERT_GE(cow_fd, 0);
- auto writer = std::make_unique<CompressedSnapshotWriter>(options);
- writer->SetSourceDevice(base_->path);
- ASSERT_TRUE(writer->SetCowDevice(std::move(cow_fd)));
- ASSERT_TRUE(writer->Initialize());
+ auto writer = CreateCowWriter(kDefaultCowVersion, options, std::move(cow_fd));
ASSERT_NO_FATAL_FAILURE(WriteCow(writer.get()));
ASSERT_NO_FATAL_FAILURE(TestReads(writer.get()));
}
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
similarity index 62%
rename from fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
index 2c1187f..31b9a58 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
@@ -24,7 +24,10 @@
#include <gtest/gtest.h>
#include <libsnapshot/cow_reader.h>
#include <libsnapshot/cow_writer.h>
+#include "cow_decompress.h"
+#include "writer_v2.h"
+using android::base::unique_fd;
using testing::AssertionFailure;
using testing::AssertionResult;
using testing::AssertionSuccess;
@@ -41,57 +44,47 @@
virtual void TearDown() override { cow_ = nullptr; }
+ unique_fd GetCowFd() { return unique_fd{dup(cow_->fd)}; }
+
std::unique_ptr<TemporaryFile> cow_;
};
-// Sink that always appends to the end of a string.
-class StringSink : public IByteSink {
- public:
- void* GetBuffer(size_t requested, size_t* actual) override {
- size_t old_size = stream_.size();
- stream_.resize(old_size + requested, '\0');
- *actual = requested;
- return stream_.data() + old_size;
- }
- bool ReturnData(void*, size_t) override { return true; }
- void Reset() { stream_.clear(); }
-
- std::string& stream() { return stream_; }
-
- private:
- std::string stream_;
-};
+// Helper to check read sizes.
+static inline bool ReadData(CowReader& reader, const CowOperation* op, void* buffer, size_t size) {
+ return reader.ReadData(op, buffer, size) == size;
+}
TEST_F(CowTest, CopyContiguous) {
CowOptions options;
options.cluster_ops = 0;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
ASSERT_TRUE(writer.AddCopy(10, 1000, 100));
ASSERT_TRUE(writer.Finalize());
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader;
- CowHeader header;
- CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd));
- ASSERT_TRUE(reader.GetHeader(&header));
- ASSERT_TRUE(reader.GetFooter(&footer));
- ASSERT_EQ(header.magic, kCowMagicNumber);
- ASSERT_EQ(header.major_version, kCowVersionMajor);
- ASSERT_EQ(header.minor_version, kCowVersionMinor);
+
+ const auto& header = reader.GetHeader();
+ ASSERT_EQ(header.prefix.magic, kCowMagicNumber);
+ ASSERT_EQ(header.prefix.major_version, kCowVersionMajor);
+ ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
+
+ CowFooter footer;
+ ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 100);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
+ ASSERT_FALSE(iter->AtEnd());
size_t i = 0;
- while (!iter->Done()) {
- auto op = &iter->Get();
+ while (!iter->AtEnd()) {
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
ASSERT_EQ(op->compression, kCowCompressNone);
ASSERT_EQ(op->data_length, 0);
@@ -107,9 +100,9 @@
TEST_F(CowTest, ReadWrite) {
CowOptions options;
options.cluster_ops = 0;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -122,21 +115,22 @@
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader;
- CowHeader header;
- CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd));
- ASSERT_TRUE(reader.GetHeader(&header));
- ASSERT_TRUE(reader.GetFooter(&footer));
- ASSERT_EQ(header.magic, kCowMagicNumber);
- ASSERT_EQ(header.major_version, kCowVersionMajor);
- ASSERT_EQ(header.minor_version, kCowVersionMinor);
+
+ const auto& header = reader.GetHeader();
+ ASSERT_EQ(header.prefix.magic, kCowMagicNumber);
+ ASSERT_EQ(header.prefix.major_version, kCowVersionMajor);
+ ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
+
+ CowFooter footer;
+ ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 4);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
ASSERT_EQ(op->compression, kCowCompressNone);
@@ -144,22 +138,22 @@
ASSERT_EQ(op->new_block, 10);
ASSERT_EQ(op->source, 20);
- StringSink sink;
+ std::string sink(data.size(), '\0');
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ 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(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
// Note: the zero operation gets split into two blocks.
ASSERT_EQ(op->type, kCowZeroOp);
@@ -169,8 +163,8 @@
ASSERT_EQ(op->source, 0);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
ASSERT_EQ(op->compression, kCowCompressNone);
@@ -179,15 +173,15 @@
ASSERT_EQ(op->source, 0);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, ReadWriteXor) {
CowOptions options;
options.cluster_ops = 0;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -200,21 +194,22 @@
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader;
- CowHeader header;
- CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd));
- ASSERT_TRUE(reader.GetHeader(&header));
- ASSERT_TRUE(reader.GetFooter(&footer));
- ASSERT_EQ(header.magic, kCowMagicNumber);
- ASSERT_EQ(header.major_version, kCowVersionMajor);
- ASSERT_EQ(header.minor_version, kCowVersionMinor);
+
+ const auto& header = reader.GetHeader();
+ ASSERT_EQ(header.prefix.magic, kCowMagicNumber);
+ ASSERT_EQ(header.prefix.major_version, kCowVersionMajor);
+ ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
+
+ CowFooter footer;
+ ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 4);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
ASSERT_EQ(op->compression, kCowCompressNone);
@@ -222,23 +217,23 @@
ASSERT_EQ(op->new_block, 10);
ASSERT_EQ(op->source, 20);
- StringSink sink;
+ std::string sink(data.size(), '\0');
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ 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_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data);
+ ASSERT_EQ(GetCowOpSourceInfoData(op), 98314); // 4096 * 24 + 10
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
// Note: the zero operation gets split into two blocks.
ASSERT_EQ(op->type, kCowZeroOp);
@@ -248,8 +243,8 @@
ASSERT_EQ(op->source, 0);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
ASSERT_EQ(op->compression, kCowCompressNone);
@@ -258,16 +253,16 @@
ASSERT_EQ(op->source, 0);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, CompressGz) {
CowOptions options;
options.cluster_ops = 0;
options.compression = "gz";
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -282,29 +277,233 @@
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
- StringSink sink;
+ 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(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
+class CompressionTest : public CowTest, public testing::WithParamInterface<const char*> {};
+
+TEST_P(CompressionTest, ThreadedBatchWrites) {
+ CowOptions options;
+ options.compression = GetParam();
+ options.num_compress_threads = 2;
+
+ CowWriterV2 writer(options, GetCowFd());
+
+ ASSERT_TRUE(writer.Initialize());
+
+ std::string xor_data = "This is test data-1. Testing xor";
+ xor_data.resize(options.block_size, '\0');
+ ASSERT_TRUE(writer.AddXorBlocks(50, xor_data.data(), xor_data.size(), 24, 10));
+
+ std::string data = "This is test data-2. Testing replace ops";
+ data.resize(options.block_size * 2048, '\0');
+ ASSERT_TRUE(writer.AddRawBlocks(100, data.data(), data.size()));
+
+ std::string data2 = "This is test data-3. Testing replace ops";
+ data2.resize(options.block_size * 259, '\0');
+ ASSERT_TRUE(writer.AddRawBlocks(6000, data2.data(), data2.size()));
+
+ std::string data3 = "This is test data-4. Testing replace ops";
+ data3.resize(options.block_size, '\0');
+ ASSERT_TRUE(writer.AddRawBlocks(9000, data3.data(), data3.size()));
+
+ ASSERT_TRUE(writer.Finalize());
+
+ int expected_blocks = (1 + 2048 + 259 + 1);
+ ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
+
+ CowReader reader;
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+
+ auto iter = reader.GetOpIter();
+ ASSERT_NE(iter, nullptr);
+
+ int total_blocks = 0;
+ while (!iter->AtEnd()) {
+ auto op = iter->Get();
+
+ if (op->type == kCowXorOp) {
+ total_blocks += 1;
+ std::string sink(xor_data.size(), '\0');
+ ASSERT_EQ(op->new_block, 50);
+ ASSERT_EQ(GetCowOpSourceInfoData(op), 98314); // 4096 * 24 + 10
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, xor_data);
+ }
+
+ if (op->type == kCowReplaceOp) {
+ total_blocks += 1;
+ if (op->new_block == 100) {
+ data.resize(options.block_size);
+ std::string sink(data.size(), '\0');
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink.size(), data.size());
+ ASSERT_EQ(sink, data);
+ }
+ if (op->new_block == 6000) {
+ data2.resize(options.block_size);
+ std::string sink(data2.size(), '\0');
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data2);
+ }
+ if (op->new_block == 9000) {
+ std::string sink(data3.size(), '\0');
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data3);
+ }
+ }
+
+ iter->Next();
+ }
+
+ ASSERT_EQ(total_blocks, expected_blocks);
+}
+
+TEST_P(CompressionTest, NoBatchWrites) {
+ CowOptions options;
+ options.compression = GetParam();
+ options.num_compress_threads = 1;
+ options.cluster_ops = 0;
+
+ CowWriterV2 writer(options, GetCowFd());
+
+ ASSERT_TRUE(writer.Initialize());
+
+ std::string data = "Testing replace ops without batch writes";
+ data.resize(options.block_size * 1024, '\0');
+ ASSERT_TRUE(writer.AddRawBlocks(50, data.data(), data.size()));
+
+ std::string data2 = "Testing odd blocks without batch writes";
+ data2.resize(options.block_size * 111, '\0');
+ ASSERT_TRUE(writer.AddRawBlocks(3000, data2.data(), data2.size()));
+
+ std::string data3 = "Testing single 4k block";
+ data3.resize(options.block_size, '\0');
+ ASSERT_TRUE(writer.AddRawBlocks(5000, data3.data(), data3.size()));
+
+ ASSERT_TRUE(writer.Finalize());
+
+ int expected_blocks = (1024 + 111 + 1);
+ ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
+
+ CowReader reader;
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+
+ auto iter = reader.GetOpIter();
+ ASSERT_NE(iter, nullptr);
+
+ int total_blocks = 0;
+ while (!iter->AtEnd()) {
+ auto op = iter->Get();
+
+ if (op->type == kCowReplaceOp) {
+ total_blocks += 1;
+ if (op->new_block == 50) {
+ data.resize(options.block_size);
+ std::string sink(data.size(), '\0');
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data);
+ }
+ if (op->new_block == 3000) {
+ data2.resize(options.block_size);
+ std::string sink(data2.size(), '\0');
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data2);
+ }
+ if (op->new_block == 5000) {
+ std::string sink(data3.size(), '\0');
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data3);
+ }
+ }
+
+ iter->Next();
+ }
+
+ ASSERT_EQ(total_blocks, expected_blocks);
+}
+
+template <typename T>
+class HorribleStream : public IByteStream {
+ public:
+ HorribleStream(const std::basic_string<T>& input) : input_(input) {}
+
+ ssize_t Read(void* buffer, size_t length) override {
+ if (pos_ >= input_.size()) {
+ return 0;
+ }
+ if (length) {
+ *reinterpret_cast<char*>(buffer) = input_[pos_];
+ }
+ pos_++;
+ return 1;
+ }
+ size_t Size() const override { return input_.size(); }
+
+ private:
+ std::basic_string<T> input_;
+ size_t pos_ = 0;
+};
+
+TEST(HorribleStream, ReadFully) {
+ std::string expected = "this is some data";
+
+ HorribleStream<char> stream(expected);
+
+ std::string buffer(expected.size(), '\0');
+ ASSERT_TRUE(stream.ReadFully(buffer.data(), buffer.size()));
+ ASSERT_EQ(buffer, expected);
+}
+
+TEST_P(CompressionTest, HorribleStream) {
+ if (strcmp(GetParam(), "none") == 0) {
+ GTEST_SKIP();
+ }
+
+ auto algorithm = CompressionAlgorithmFromString(GetParam());
+ ASSERT_TRUE(algorithm.has_value());
+
+ std::string expected = "The quick brown fox jumps over the lazy dog.";
+ expected.resize(4096, '\0');
+
+ auto result = CompressWorker::Compress(*algorithm, expected.data(), expected.size());
+ ASSERT_FALSE(result.empty());
+
+ HorribleStream<uint8_t> stream(result);
+ auto decomp = IDecompressor::FromString(GetParam());
+ ASSERT_NE(decomp, nullptr);
+ decomp->set_stream(&stream);
+
+ expected = expected.substr(10, 500);
+
+ std::string buffer(expected.size(), '\0');
+ ASSERT_EQ(decomp->Decompress(buffer.data(), 500, 4096, 10), 500);
+ ASSERT_EQ(buffer, expected);
+}
+
+INSTANTIATE_TEST_SUITE_P(AllCompressors, CompressionTest,
+ testing::Values("none", "gz", "brotli", "lz4"));
+
TEST_F(CowTest, ClusterCompressGz) {
CowOptions options;
options.compression = "gz";
options.cluster_ops = 2;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -323,52 +522,53 @@
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
- StringSink sink;
+ 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(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
- sink.Reset();
- ASSERT_EQ(op->compression, kCowCompressGz);
+ sink = {};
+ sink.resize(data2.size(), '\0');
+ ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
ASSERT_EQ(op->data_length, 41); // compressed!
ASSERT_EQ(op->new_block, 51);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data2);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data2);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, CompressTwoBlocks) {
CowOptions options;
options.compression = "gz";
options.cluster_ops = 0;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size * 2, '\0');
@@ -383,68 +583,28 @@
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
+ ASSERT_FALSE(iter->AtEnd());
iter->Next();
- ASSERT_FALSE(iter->Done());
+ ASSERT_FALSE(iter->AtEnd());
- StringSink sink;
+ std::string sink(options.block_size, '\0');
- auto op = &iter->Get();
+ 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(reader.ReadData(*op, &sink));
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
}
-// Only return 1-byte buffers, to stress test the partial read logic in
-// CowReader.
-class HorribleStringSink : public StringSink {
- public:
- void* GetBuffer(size_t, size_t* actual) override { return StringSink::GetBuffer(1, actual); }
-};
-
-class CompressionTest : public CowTest, public testing::WithParamInterface<const char*> {};
-
-TEST_P(CompressionTest, HorribleSink) {
- CowOptions options;
- options.compression = GetParam();
- options.cluster_ops = 0;
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_->fd));
-
- std::string data = "This is some data, believe it";
- data.resize(options.block_size, '\0');
-
- ASSERT_TRUE(writer.AddRawBlocks(50, data.data(), data.size()));
- ASSERT_TRUE(writer.Finalize());
-
- ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
-
- CowReader reader;
- ASSERT_TRUE(reader.Parse(cow_->fd));
-
- auto iter = reader.GetOpIter();
- ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
-
- HorribleStringSink sink;
- auto op = &iter->Get();
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data);
-}
-
-INSTANTIATE_TEST_SUITE_P(CowApi, CompressionTest, testing::Values("none", "gz", "brotli"));
-
TEST_F(CowTest, GetSize) {
CowOptions options;
options.cluster_ops = 0;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
if (ftruncate(cow_->fd, 0) < 0) {
perror("Fails to set temp file size");
FAIL();
}
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -465,8 +625,8 @@
TEST_F(CowTest, AppendLabelSmall) {
CowOptions options;
options.cluster_ops = 0;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -476,8 +636,8 @@
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 3));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({3}));
std::string data2 = "More data!";
data2.resize(options.block_size, '\0');
@@ -497,42 +657,43 @@
ASSERT_TRUE(reader.GetLastLabel(&label));
ASSERT_EQ(label, 3);
- StringSink sink;
+ std::string sink(data.size(), '\0');
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data);
iter->Next();
- sink.Reset();
+ sink = {};
+ sink.resize(data2.size(), '\0');
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 3);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data2);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data2);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendLabelMissing) {
CowOptions options;
options.cluster_ops = 0;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(writer->AddLabel(0));
std::string data = "This is some data, believe it";
@@ -544,9 +705,9 @@
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_FALSE(writer->InitializeAppend(cow_->fd, 1));
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 0));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_FALSE(writer->Initialize({1}));
+ ASSERT_TRUE(writer->Initialize({0}));
ASSERT_TRUE(writer->AddZeroBlocks(51, 1));
ASSERT_TRUE(writer->Finalize());
@@ -561,32 +722,30 @@
CowReader reader;
ASSERT_TRUE(reader.Parse(cow_->fd));
- StringSink sink;
-
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 0);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendExtendedCorrupted) {
CowOptions options;
options.cluster_ops = 0;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(writer->AddLabel(5));
@@ -608,8 +767,8 @@
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 5));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({5}));
ASSERT_TRUE(writer->Finalize());
@@ -621,25 +780,23 @@
CowReader reader;
ASSERT_TRUE(reader.Parse(cow_->fd));
- StringSink sink;
-
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendbyLabel) {
CowOptions options;
options.cluster_ops = 0;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size * 2, '\0');
@@ -657,9 +814,9 @@
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_FALSE(writer->InitializeAppend(cow_->fd, 12));
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 5));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_FALSE(writer->Initialize({12}));
+ ASSERT_TRUE(writer->Initialize({5}));
// This should drop label 6
ASSERT_TRUE(writer->Finalize());
@@ -672,62 +829,62 @@
CowReader reader;
ASSERT_TRUE(reader.Parse(cow_->fd));
- StringSink sink;
+ std::string sink(options.block_size, '\0');
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data.substr(0, options.block_size));
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data.substr(0, options.block_size));
iter->Next();
- sink.Reset();
+ sink = {};
+ sink.resize(options.block_size, '\0');
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data.substr(options.block_size, 2 * options.block_size));
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data.substr(options.block_size, 2 * options.block_size));
iter->Next();
- sink.Reset();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 4);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, ClusterTest) {
CowOptions options;
options.cluster_ops = 4;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -753,87 +910,86 @@
CowReader reader;
ASSERT_TRUE(reader.Parse(cow_->fd));
- StringSink sink;
+ std::string sink(data.size(), '\0');
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data.substr(0, options.block_size));
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data.substr(0, options.block_size));
iter->Next();
- sink.Reset();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 4);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 6);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, ClusterAppendTest) {
CowOptions options;
options.cluster_ops = 3;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(writer->AddLabel(50));
ASSERT_TRUE(writer->Finalize()); // Adds a cluster op, should be dropped on append
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 50));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({50}));
std::string data2 = "More data!";
data2.resize(options.block_size, '\0');
@@ -853,40 +1009,40 @@
ASSERT_TRUE(reader.GetLastLabel(&label));
ASSERT_EQ(label, 50);
- StringSink sink;
+ std::string sink(data2.size(), '\0');
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
- ASSERT_FALSE(iter->Done());
- auto op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ auto op = iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 50);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
- ASSERT_TRUE(reader.ReadData(*op, &sink));
- ASSERT_EQ(sink.stream(), data2);
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
+ ASSERT_EQ(sink, data2);
iter->Next();
- ASSERT_FALSE(iter->Done());
- op = &iter->Get();
+ ASSERT_FALSE(iter->AtEnd());
+ op = iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendAfterFinalize) {
CowOptions options;
options.cluster_ops = 0;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -906,29 +1062,28 @@
ASSERT_TRUE(reader.Parse(cow_->fd));
}
-AssertionResult WriteDataBlock(CowWriter* writer, uint64_t new_block, std::string data) {
- data.resize(writer->options().block_size, '\0');
+AssertionResult WriteDataBlock(ICowWriter* writer, uint64_t new_block, std::string data) {
+ data.resize(writer->GetBlockSize(), '\0');
if (!writer->AddRawBlocks(new_block, data.data(), data.size())) {
return AssertionFailure() << "Failed to add raw block";
}
return AssertionSuccess();
}
-AssertionResult CompareDataBlock(CowReader* reader, const CowOperation& op,
+AssertionResult CompareDataBlock(CowReader* reader, const CowOperation* op,
const std::string& data) {
- CowHeader header;
- reader->GetHeader(&header);
+ const auto& header = reader->GetHeader();
std::string cmp = data;
cmp.resize(header.block_size, '\0');
- StringSink sink;
- if (!reader->ReadData(op, &sink)) {
+ std::string sink(cmp.size(), '\0');
+ if (!reader->ReadData(op, sink.data(), sink.size())) {
return AssertionFailure() << "Failed to read data block";
}
- if (cmp != sink.stream()) {
+ if (cmp != sink) {
return AssertionFailure() << "Data blocks did not match, expected " << cmp << ", got "
- << sink.stream();
+ << sink;
}
return AssertionSuccess();
@@ -937,8 +1092,8 @@
TEST_F(CowTest, ResumeMidCluster) {
CowOptions options;
options.cluster_ops = 7;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(WriteDataBlock(writer.get(), 1, "Block 1"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 2, "Block 2"));
@@ -948,8 +1103,8 @@
ASSERT_TRUE(WriteDataBlock(writer.get(), 4, "Block 4"));
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({1}));
ASSERT_TRUE(WriteDataBlock(writer.get(), 4, "Block 4"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 5, "Block 5"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 6, "Block 6"));
@@ -967,18 +1122,18 @@
size_t max_in_cluster = 0;
size_t num_in_cluster = 0;
size_t num_clusters = 0;
- while (!iter->Done()) {
+ while (!iter->AtEnd()) {
const auto& op = iter->Get();
num_in_cluster++;
max_in_cluster = std::max(max_in_cluster, num_in_cluster);
- if (op.type == kCowReplaceOp) {
+ if (op->type == kCowReplaceOp) {
num_replace++;
- ASSERT_EQ(op.new_block, num_replace);
+ ASSERT_EQ(op->new_block, num_replace);
ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace)));
- } else if (op.type == kCowClusterOp) {
+ } else if (op->type == kCowClusterOp) {
num_in_cluster = 0;
num_clusters++;
}
@@ -994,8 +1149,8 @@
CowOptions options;
int cluster_ops = 5;
options.cluster_ops = cluster_ops;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(WriteDataBlock(writer.get(), 1, "Block 1"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 2, "Block 2"));
@@ -1009,8 +1164,8 @@
ASSERT_TRUE(WriteDataBlock(writer.get(), 8, "Block 8"));
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({1}));
ASSERT_TRUE(WriteDataBlock(writer.get(), 4, "Block 4"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 5, "Block 5"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 6, "Block 6"));
@@ -1028,18 +1183,18 @@
size_t max_in_cluster = 0;
size_t num_in_cluster = 0;
size_t num_clusters = 0;
- while (!iter->Done()) {
+ while (!iter->AtEnd()) {
const auto& op = iter->Get();
num_in_cluster++;
max_in_cluster = std::max(max_in_cluster, num_in_cluster);
- if (op.type == kCowReplaceOp) {
+ if (op->type == kCowReplaceOp) {
num_replace++;
- ASSERT_EQ(op.new_block, num_replace);
+ ASSERT_EQ(op->new_block, num_replace);
ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace)));
- } else if (op.type == kCowClusterOp) {
+ } else if (op->type == kCowClusterOp) {
num_in_cluster = 0;
num_clusters++;
}
@@ -1054,8 +1209,8 @@
TEST_F(CowTest, DeleteMidCluster) {
CowOptions options;
options.cluster_ops = 7;
- auto writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(WriteDataBlock(writer.get(), 1, "Block 1"));
ASSERT_TRUE(WriteDataBlock(writer.get(), 2, "Block 2"));
@@ -1067,8 +1222,8 @@
ASSERT_TRUE(WriteDataBlock(writer.get(), 6, "Block 6"));
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({1}));
ASSERT_TRUE(writer->Finalize());
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
@@ -1080,17 +1235,17 @@
size_t max_in_cluster = 0;
size_t num_in_cluster = 0;
size_t num_clusters = 0;
- while (!iter->Done()) {
+ while (!iter->AtEnd()) {
const auto& op = iter->Get();
num_in_cluster++;
max_in_cluster = std::max(max_in_cluster, num_in_cluster);
- if (op.type == kCowReplaceOp) {
+ if (op->type == kCowReplaceOp) {
num_replace++;
- ASSERT_EQ(op.new_block, num_replace);
+ ASSERT_EQ(op->new_block, num_replace);
ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace)));
- } else if (op.type == kCowClusterOp) {
+ } else if (op->type == kCowClusterOp) {
num_in_cluster = 0;
num_clusters++;
}
@@ -1104,14 +1259,14 @@
TEST_F(CowTest, BigSeqOp) {
CowOptions options;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
const int seq_len = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t) + 1;
uint32_t sequence[seq_len];
for (int i = 0; i < seq_len; i++) {
sequence[i] = i + 1;
}
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
ASSERT_TRUE(writer.AddSequenceData(seq_len, sequence));
ASSERT_TRUE(writer.AddZeroBlocks(1, seq_len));
@@ -1124,26 +1279,26 @@
auto iter = reader.GetRevMergeOpIter();
for (int i = 0; i < seq_len; i++) {
- ASSERT_TRUE(!iter->Done());
+ ASSERT_TRUE(!iter->AtEnd());
const auto& op = iter->Get();
- ASSERT_EQ(op.new_block, seq_len - i);
+ ASSERT_EQ(op->new_block, seq_len - i);
iter->Next();
}
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, MissingSeqOp) {
CowOptions options;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
const int seq_len = 10;
uint32_t sequence[seq_len];
for (int i = 0; i < seq_len; i++) {
sequence[i] = i + 1;
}
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
ASSERT_TRUE(writer.AddSequenceData(seq_len, sequence));
ASSERT_TRUE(writer.AddZeroBlocks(1, seq_len - 1));
@@ -1157,14 +1312,14 @@
TEST_F(CowTest, ResumeSeqOp) {
CowOptions options;
- auto writer = std::make_unique<CowWriter>(options);
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
const int seq_len = 10;
uint32_t sequence[seq_len];
for (int i = 0; i < seq_len; i++) {
sequence[i] = i + 1;
}
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(writer->AddSequenceData(seq_len, sequence));
ASSERT_TRUE(writer->AddZeroBlocks(1, seq_len / 2));
@@ -1175,10 +1330,10 @@
auto reader = std::make_unique<CowReader>();
ASSERT_TRUE(reader->Parse(cow_->fd, 1));
auto itr = reader->GetRevMergeOpIter();
- ASSERT_TRUE(itr->Done());
+ ASSERT_TRUE(itr->AtEnd());
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize({1}));
ASSERT_TRUE(writer->AddZeroBlocks(1 + seq_len / 2, seq_len / 2));
ASSERT_TRUE(writer->Finalize());
@@ -1190,27 +1345,27 @@
auto iter = reader->GetRevMergeOpIter();
uint64_t expected_block = 10;
- while (!iter->Done() && expected_block > 0) {
- ASSERT_FALSE(iter->Done());
+ while (!iter->AtEnd() && expected_block > 0) {
+ ASSERT_FALSE(iter->AtEnd());
const auto& op = iter->Get();
- ASSERT_EQ(op.new_block, expected_block);
+ ASSERT_EQ(op->new_block, expected_block);
iter->Next();
expected_block--;
}
ASSERT_EQ(expected_block, 0);
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, RevMergeOpItrTest) {
CowOptions options;
options.cluster_ops = 5;
options.num_merge_ops = 1;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
uint32_t sequence[] = {2, 10, 6, 7, 3, 5};
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
ASSERT_TRUE(writer.AddSequenceData(6, sequence));
ASSERT_TRUE(writer.AddCopy(6, 13));
@@ -1241,25 +1396,25 @@
auto iter = reader.GetRevMergeOpIter();
auto expected_new_block = revMergeOpSequence.begin();
- while (!iter->Done() && expected_new_block != revMergeOpSequence.end()) {
+ while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) {
const auto& op = iter->Get();
- ASSERT_EQ(op.new_block, *expected_new_block);
+ ASSERT_EQ(op->new_block, *expected_new_block);
iter->Next();
expected_new_block++;
}
ASSERT_EQ(expected_new_block, revMergeOpSequence.end());
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, LegacyRevMergeOpItrTest) {
CowOptions options;
options.cluster_ops = 5;
options.num_merge_ops = 1;
- CowWriter writer(options);
+ CowWriterV2 writer(options, GetCowFd());
- ASSERT_TRUE(writer.Initialize(cow_->fd));
+ ASSERT_TRUE(writer.Initialize());
ASSERT_TRUE(writer.AddCopy(2, 11));
ASSERT_TRUE(writer.AddCopy(10, 12));
@@ -1290,16 +1445,16 @@
auto iter = reader.GetRevMergeOpIter();
auto expected_new_block = revMergeOpSequence.begin();
- while (!iter->Done() && expected_new_block != revMergeOpSequence.end()) {
+ while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) {
const auto& op = iter->Get();
- ASSERT_EQ(op.new_block, *expected_new_block);
+ ASSERT_EQ(op->new_block, *expected_new_block);
iter->Next();
expected_new_block++;
}
ASSERT_EQ(expected_new_block, revMergeOpSequence.end());
- ASSERT_TRUE(iter->Done());
+ ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, InvalidMergeOrderTest) {
@@ -1308,10 +1463,10 @@
options.num_merge_ops = 1;
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
- auto writer = std::make_unique<CowWriter>(options);
+ auto writer = std::make_unique<CowWriterV2>(options, GetCowFd());
CowReader reader;
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(writer->AddCopy(3, 2));
ASSERT_TRUE(writer->AddCopy(2, 1));
@@ -1320,14 +1475,14 @@
ASSERT_TRUE(reader.Parse(cow_->fd));
ASSERT_TRUE(reader.VerifyMergeOps());
- ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
+ ASSERT_TRUE(writer->Initialize({1}));
ASSERT_TRUE(writer->AddCopy(4, 2));
ASSERT_TRUE(writer->Finalize());
ASSERT_TRUE(reader.Parse(cow_->fd));
ASSERT_FALSE(reader.VerifyMergeOps());
- writer = std::make_unique<CowWriter>(options);
- ASSERT_TRUE(writer->Initialize(cow_->fd));
+ writer = std::make_unique<CowWriterV2>(options, GetCowFd());
+ ASSERT_TRUE(writer->Initialize());
ASSERT_TRUE(writer->AddCopy(2, 1));
ASSERT_TRUE(writer->AddXorBlocks(3, &data, data.size(), 1, 1));
ASSERT_TRUE(writer->Finalize());
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp
new file mode 100644
index 0000000..ff34c59
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.cpp
@@ -0,0 +1,195 @@
+// 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 "writer_base.h"
+
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include "snapshot_reader.h"
+
+// The info messages here are spammy, but as useful for update_engine. Disable
+// them when running on the host.
+#ifdef __ANDROID__
+#define LOG_INFO LOG(INFO)
+#else
+#define LOG_INFO LOG(VERBOSE)
+#endif
+
+namespace android {
+namespace snapshot {
+
+using android::base::borrowed_fd;
+using android::base::unique_fd;
+
+namespace {
+std::string GetFdPath(borrowed_fd fd) {
+ const auto fd_path = "/proc/self/fd/" + std::to_string(fd.get());
+ std::string file_path(512, '\0');
+ const auto err = readlink(fd_path.c_str(), file_path.data(), file_path.size());
+ if (err <= 0) {
+ PLOG(ERROR) << "Failed to determine path for fd " << fd.get();
+ file_path.clear();
+ } else {
+ file_path.resize(err);
+ }
+ return file_path;
+}
+} // namespace
+
+CowWriterBase::CowWriterBase(const CowOptions& options, unique_fd&& fd)
+ : options_(options), fd_(std::move(fd)) {}
+
+bool CowWriterBase::InitFd() {
+ if (fd_.get() < 0) {
+ fd_.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
+ if (fd_ < 0) {
+ PLOG(ERROR) << "open /dev/null failed";
+ return false;
+ }
+ is_dev_null_ = true;
+ return true;
+ }
+
+ struct stat stat {};
+ if (fstat(fd_.get(), &stat) < 0) {
+ PLOG(ERROR) << "fstat failed";
+ return false;
+ }
+ const auto file_path = GetFdPath(fd_);
+ is_block_device_ = S_ISBLK(stat.st_mode);
+ if (is_block_device_) {
+ uint64_t size_in_bytes = 0;
+ if (ioctl(fd_.get(), BLKGETSIZE64, &size_in_bytes)) {
+ PLOG(ERROR) << "Failed to get total size for: " << fd_.get();
+ return false;
+ }
+ cow_image_size_ = size_in_bytes;
+ LOG_INFO << "COW image " << file_path << " has size " << size_in_bytes;
+ } else {
+ LOG_INFO << "COW image " << file_path
+ << " is not a block device, assuming unlimited space.";
+ }
+ return true;
+}
+
+bool CowWriterBase::AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
+ CHECK(num_blocks != 0);
+
+ for (size_t i = 0; i < num_blocks; i++) {
+ if (!ValidateNewBlock(new_block + i)) {
+ return false;
+ }
+ }
+
+ return EmitCopy(new_block, old_block, num_blocks);
+}
+
+bool CowWriterBase::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
+ if (size % options_.block_size != 0) {
+ LOG(ERROR) << "AddRawBlocks: size " << size << " is not a multiple of "
+ << options_.block_size;
+ return false;
+ }
+
+ uint64_t num_blocks = size / options_.block_size;
+ uint64_t last_block = new_block_start + num_blocks - 1;
+ if (!ValidateNewBlock(last_block)) {
+ return false;
+ }
+ return EmitRawBlocks(new_block_start, data, size);
+}
+
+bool CowWriterBase::AddXorBlocks(uint32_t new_block_start, const void* data, size_t size,
+ uint32_t old_block, uint16_t offset) {
+ if (size % options_.block_size != 0) {
+ LOG(ERROR) << "AddRawBlocks: size " << size << " is not a multiple of "
+ << options_.block_size;
+ return false;
+ }
+
+ uint64_t num_blocks = size / options_.block_size;
+ uint64_t last_block = new_block_start + num_blocks - 1;
+ if (!ValidateNewBlock(last_block)) {
+ return false;
+ }
+ if (offset >= options_.block_size) {
+ LOG(ERROR) << "AddXorBlocks: offset " << offset << " is not less than "
+ << options_.block_size;
+ }
+ return EmitXorBlocks(new_block_start, data, size, old_block, offset);
+}
+
+bool CowWriterBase::AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
+ uint64_t last_block = new_block_start + num_blocks - 1;
+ if (!ValidateNewBlock(last_block)) {
+ return false;
+ }
+ return EmitZeroBlocks(new_block_start, num_blocks);
+}
+
+bool CowWriterBase::AddLabel(uint64_t label) {
+ return EmitLabel(label);
+}
+
+bool CowWriterBase::AddSequenceData(size_t num_ops, const uint32_t* data) {
+ return EmitSequenceData(num_ops, data);
+}
+
+bool CowWriterBase::ValidateNewBlock(uint64_t new_block) {
+ if (options_.max_blocks && new_block >= options_.max_blocks.value()) {
+ LOG(ERROR) << "New block " << new_block << " exceeds maximum block count "
+ << options_.max_blocks.value();
+ return false;
+ }
+ return true;
+}
+
+std::unique_ptr<ICowReader> CowWriterBase::OpenReader() {
+ unique_fd cow_fd(fcntl(fd_.get(), F_DUPFD | F_DUPFD_CLOEXEC, 0));
+ if (cow_fd < 0) {
+ PLOG(ERROR) << "CowWriterV2::OpenReander: dup COW device";
+ return nullptr;
+ }
+
+ auto cow = std::make_unique<CowReader>();
+ if (!cow->Parse(std::move(cow_fd))) {
+ LOG(ERROR) << "CowWriterV2::OpenReader: unable to read COW";
+ return nullptr;
+ }
+ return cow;
+}
+
+std::unique_ptr<chromeos_update_engine::FileDescriptor> CowWriterBase::OpenFileDescriptor(
+ const std::optional<std::string>& source_device) {
+ auto reader = OpenReader();
+ if (!reader) {
+ return nullptr;
+ }
+
+ std::optional<uint64_t> block_dev_size;
+ if (options_.max_blocks) {
+ block_dev_size = {*options_.max_blocks * options_.block_size};
+ }
+
+ return std::make_unique<CompressedSnapshotReader>(std::move(reader), source_device,
+ block_dev_size);
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h
new file mode 100644
index 0000000..c8b4772
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_base.h
@@ -0,0 +1,74 @@
+// 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 <libsnapshot/cow_writer.h>
+
+namespace android {
+namespace snapshot {
+
+class CowWriterBase : public ICowWriter {
+ public:
+ CowWriterBase(const CowOptions& options, android::base::unique_fd&& fd);
+ virtual ~CowWriterBase() {}
+
+ // Set up the writer.
+ // The file starts from the beginning.
+ //
+ // If fd is < 0, the CowWriter will be opened against /dev/null. This is for
+ // computing COW sizes without using storage space.
+ //
+ // If a label is given, any operations after the given label will be dropped.
+ // If the given label is not found, Initialize will fail.
+ virtual bool Initialize(std::optional<uint64_t> label = {}) = 0;
+
+ bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
+ bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
+ bool AddXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
+ uint16_t offset) override;
+ bool AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
+ bool AddLabel(uint64_t label) override;
+ bool AddSequenceData(size_t num_ops, const uint32_t* data) override;
+ uint32_t GetBlockSize() const override { return options_.block_size; }
+ std::optional<uint32_t> GetMaxBlocks() const override { return options_.max_blocks; }
+ std::unique_ptr<ICowReader> OpenReader() override;
+ std::unique_ptr<FileDescriptor> OpenFileDescriptor(
+ const std::optional<std::string>& source_device) override;
+
+ const CowOptions& options() const { return options_; }
+
+ protected:
+ virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0;
+ virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0;
+ virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
+ uint32_t old_block, uint16_t offset) = 0;
+ virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) = 0;
+ virtual bool EmitLabel(uint64_t label) = 0;
+ virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) = 0;
+
+ bool InitFd();
+ bool ValidateNewBlock(uint64_t new_block);
+
+ CowOptions options_;
+ CowHeader header_{};
+
+ android::base::unique_fd fd_;
+ bool is_dev_null_ = false;
+ bool is_block_device_ = false;
+ uint64_t cow_image_size_ = INT64_MAX;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
new file mode 100644
index 0000000..c549969
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -0,0 +1,706 @@
+//
+// Copyright (C) 2020 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 "writer_v2.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <limits>
+#include <queue>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
+#include <brotli/encode.h>
+#include <libsnapshot/cow_format.h>
+#include <libsnapshot/cow_reader.h>
+#include <libsnapshot/cow_writer.h>
+#include <lz4.h>
+#include <zlib.h>
+
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "parser_v2.h"
+
+// The info messages here are spammy, but as useful for update_engine. Disable
+// them when running on the host.
+#ifdef __ANDROID__
+#define LOG_INFO LOG(INFO)
+#else
+#define LOG_INFO LOG(VERBOSE)
+#endif
+
+namespace android {
+namespace snapshot {
+
+static_assert(sizeof(off_t) == sizeof(uint64_t));
+
+using android::base::unique_fd;
+
+CowWriterV2::CowWriterV2(const CowOptions& options, unique_fd&& fd)
+ : CowWriterBase(options, std::move(fd)) {
+ SetupHeaders();
+ SetupWriteOptions();
+}
+
+CowWriterV2::~CowWriterV2() {
+ for (size_t i = 0; i < compress_threads_.size(); i++) {
+ CompressWorker* worker = compress_threads_[i].get();
+ if (worker) {
+ worker->Finalize();
+ }
+ }
+
+ bool ret = true;
+ for (auto& t : threads_) {
+ ret = t.get() && ret;
+ }
+
+ if (!ret) {
+ LOG(ERROR) << "Compression failed";
+ }
+ compress_threads_.clear();
+}
+
+void CowWriterV2::SetupWriteOptions() {
+ num_compress_threads_ = options_.num_compress_threads;
+
+ if (!num_compress_threads_) {
+ num_compress_threads_ = 1;
+ // We prefer not to have more than two threads as the overhead of additional
+ // threads is far greater than cutting down compression time.
+ if (header_.cluster_ops &&
+ android::base::GetBoolProperty("ro.virtual_ab.compression.threads", false)) {
+ num_compress_threads_ = 2;
+ }
+ }
+
+ if (header_.cluster_ops &&
+ (android::base::GetBoolProperty("ro.virtual_ab.batch_writes", false) ||
+ options_.batch_write)) {
+ batch_write_ = true;
+ }
+}
+
+void CowWriterV2::SetupHeaders() {
+ header_ = {};
+ header_.prefix.magic = kCowMagicNumber;
+ header_.prefix.major_version = kCowVersionMajor;
+ header_.prefix.minor_version = kCowVersionMinor;
+ header_.prefix.header_size = sizeof(CowHeader);
+ header_.footer_size = sizeof(CowFooter);
+ header_.op_size = sizeof(CowOperation);
+ header_.block_size = options_.block_size;
+ header_.num_merge_ops = options_.num_merge_ops;
+ header_.cluster_ops = options_.cluster_ops;
+ header_.buffer_size = 0;
+ footer_ = {};
+ footer_.op.data_length = 64;
+ footer_.op.type = kCowFooterOp;
+}
+
+bool CowWriterV2::ParseOptions() {
+ auto algorithm = CompressionAlgorithmFromString(options_.compression);
+ if (!algorithm) {
+ LOG(ERROR) << "unrecognized compression: " << options_.compression;
+ return false;
+ }
+ compression_ = *algorithm;
+
+ if (options_.cluster_ops == 1) {
+ LOG(ERROR) << "Clusters must contain at least two operations to function.";
+ return false;
+ }
+ return true;
+}
+
+void CowWriterV2::InitBatchWrites() {
+ if (batch_write_) {
+ cowop_vec_ = std::make_unique<struct iovec[]>(header_.cluster_ops);
+ data_vec_ = std::make_unique<struct iovec[]>(header_.cluster_ops);
+ struct iovec* cowop_ptr = cowop_vec_.get();
+ struct iovec* data_ptr = data_vec_.get();
+ for (size_t i = 0; i < header_.cluster_ops; i++) {
+ std::unique_ptr<CowOperation> op = std::make_unique<CowOperation>();
+ cowop_ptr[i].iov_base = op.get();
+ cowop_ptr[i].iov_len = sizeof(CowOperation);
+ opbuffer_vec_.push_back(std::move(op));
+
+ std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(header_.block_size * 2);
+ data_ptr[i].iov_base = buffer.get();
+ data_ptr[i].iov_len = header_.block_size * 2;
+ databuffer_vec_.push_back(std::move(buffer));
+ }
+
+ current_op_pos_ = next_op_pos_;
+ current_data_pos_ = next_data_pos_;
+ }
+
+ std::string batch_write = batch_write_ ? "enabled" : "disabled";
+ LOG_INFO << "Batch writes: " << batch_write;
+}
+
+void CowWriterV2::InitWorkers() {
+ if (num_compress_threads_ <= 1) {
+ LOG_INFO << "Not creating new threads for compression.";
+ return;
+ }
+ for (int i = 0; i < num_compress_threads_; i++) {
+ auto wt = std::make_unique<CompressWorker>(compression_, header_.block_size);
+ threads_.emplace_back(std::async(std::launch::async, &CompressWorker::RunThread, wt.get()));
+ compress_threads_.push_back(std::move(wt));
+ }
+
+ LOG_INFO << num_compress_threads_ << " thread used for compression";
+}
+
+bool CowWriterV2::Initialize(std::optional<uint64_t> label) {
+ if (!InitFd() || !ParseOptions()) {
+ return false;
+ }
+ if (!label) {
+ if (!OpenForWrite()) {
+ return false;
+ }
+ } else {
+ if (!OpenForAppend(*label)) {
+ return false;
+ }
+ }
+
+ if (!compress_threads_.size()) {
+ InitWorkers();
+ }
+ return true;
+}
+
+void CowWriterV2::InitPos() {
+ next_op_pos_ = sizeof(header_) + header_.buffer_size;
+ cluster_size_ = header_.cluster_ops * sizeof(CowOperation);
+ if (header_.cluster_ops) {
+ next_data_pos_ = next_op_pos_ + cluster_size_;
+ } else {
+ next_data_pos_ = next_op_pos_ + sizeof(CowOperation);
+ }
+ current_cluster_size_ = 0;
+ current_data_size_ = 0;
+}
+
+bool CowWriterV2::OpenForWrite() {
+ // This limitation is tied to the data field size in CowOperation.
+ if (header_.block_size > std::numeric_limits<uint16_t>::max()) {
+ LOG(ERROR) << "Block size is too large";
+ return false;
+ }
+
+ if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek failed";
+ return false;
+ }
+
+ if (options_.scratch_space) {
+ header_.buffer_size = BUFFER_REGION_DEFAULT_SIZE;
+ }
+
+ // Headers are not complete, but this ensures the file is at the right
+ // position.
+ if (!android::base::WriteFully(fd_, &header_, sizeof(header_))) {
+ PLOG(ERROR) << "write failed";
+ return false;
+ }
+
+ if (options_.scratch_space) {
+ // Initialize the scratch space
+ std::string data(header_.buffer_size, 0);
+ if (!android::base::WriteFully(fd_, data.data(), header_.buffer_size)) {
+ PLOG(ERROR) << "writing scratch space failed";
+ return false;
+ }
+ }
+
+ if (!Sync()) {
+ LOG(ERROR) << "Header sync failed";
+ return false;
+ }
+
+ if (lseek(fd_.get(), sizeof(header_) + header_.buffer_size, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek failed";
+ return false;
+ }
+
+ InitPos();
+ InitBatchWrites();
+
+ return true;
+}
+
+bool CowWriterV2::OpenForAppend(uint64_t label) {
+ if (!ReadCowHeader(fd_, &header_)) {
+ return false;
+ }
+
+ CowParserV2 parser;
+ if (!parser.Parse(fd_, header_, {label})) {
+ return false;
+ }
+ if (header_.prefix.major_version > 2) {
+ LOG(ERROR) << "CowWriterV2 tried to open incompatible version "
+ << header_.prefix.major_version;
+ return false;
+ }
+
+ options_.block_size = header_.block_size;
+ options_.cluster_ops = header_.cluster_ops;
+
+ // Reset this, since we're going to reimport all operations.
+ footer_.op.num_ops = 0;
+ InitPos();
+
+ for (const auto& op : *parser.ops()) {
+ AddOperation(op);
+ }
+
+ if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek failed";
+ return false;
+ }
+
+ InitBatchWrites();
+
+ return EmitClusterIfNeeded();
+}
+
+bool CowWriterV2::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
+ CHECK(!merge_in_progress_);
+
+ for (size_t i = 0; i < num_blocks; i++) {
+ CowOperation op = {};
+ op.type = kCowCopyOp;
+ op.new_block = new_block + i;
+ op.source = old_block + i;
+ if (!WriteOperation(op)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CowWriterV2::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
+ return EmitBlocks(new_block_start, data, size, 0, 0, kCowReplaceOp);
+}
+
+bool CowWriterV2::EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
+ uint32_t old_block, uint16_t offset) {
+ return EmitBlocks(new_block_start, data, size, old_block, offset, kCowXorOp);
+}
+
+bool CowWriterV2::CompressBlocks(size_t num_blocks, const void* data) {
+ size_t num_threads = (num_blocks == 1) ? 1 : num_compress_threads_;
+ size_t num_blocks_per_thread = num_blocks / num_threads;
+ const uint8_t* iter = reinterpret_cast<const uint8_t*>(data);
+ compressed_buf_.clear();
+ if (num_threads <= 1) {
+ return CompressWorker::CompressBlocks(compression_, options_.block_size, data, num_blocks,
+ &compressed_buf_);
+ }
+
+ // Submit the blocks per thread. The retrieval of
+ // compressed buffers has to be done in the same order.
+ // We should not poll for completed buffers in a different order as the
+ // buffers are tightly coupled with block ordering.
+ for (size_t i = 0; i < num_threads; i++) {
+ CompressWorker* worker = compress_threads_[i].get();
+ if (i == num_threads - 1) {
+ num_blocks_per_thread = num_blocks;
+ }
+ worker->EnqueueCompressBlocks(iter, num_blocks_per_thread);
+ iter += (num_blocks_per_thread * header_.block_size);
+ num_blocks -= num_blocks_per_thread;
+ }
+
+ for (size_t i = 0; i < num_threads; i++) {
+ CompressWorker* worker = compress_threads_[i].get();
+ if (!worker->GetCompressedBuffers(&compressed_buf_)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CowWriterV2::EmitBlocks(uint64_t new_block_start, const void* data, size_t size,
+ uint64_t old_block, uint16_t offset, uint8_t type) {
+ CHECK(!merge_in_progress_);
+ const uint8_t* iter = reinterpret_cast<const uint8_t*>(data);
+
+ // Update engine can potentially send 100MB of blocks at a time. We
+ // don't want to process all those blocks in one shot as it can
+ // stress the memory. Hence, process the blocks in chunks.
+ //
+ // 1024 blocks is reasonable given we will end up using max
+ // memory of ~4MB.
+ const size_t kProcessingBlocks = 1024;
+ size_t num_blocks = (size / header_.block_size);
+ size_t i = 0;
+
+ while (num_blocks) {
+ size_t pending_blocks = (std::min(kProcessingBlocks, num_blocks));
+
+ if (compression_ && num_compress_threads_ > 1) {
+ if (!CompressBlocks(pending_blocks, iter)) {
+ return false;
+ }
+ buf_iter_ = compressed_buf_.begin();
+ CHECK(pending_blocks == compressed_buf_.size());
+ }
+
+ num_blocks -= pending_blocks;
+
+ while (i < size / header_.block_size && pending_blocks) {
+ CowOperation op = {};
+ op.new_block = new_block_start + i;
+ op.type = type;
+ if (type == kCowXorOp) {
+ op.source = (old_block + i) * header_.block_size + offset;
+ } else {
+ op.source = next_data_pos_;
+ }
+
+ if (compression_) {
+ auto data = [&, this]() {
+ if (num_compress_threads_ > 1) {
+ auto data = std::move(*buf_iter_);
+ buf_iter_++;
+ return data;
+ } else {
+ auto data =
+ CompressWorker::Compress(compression_, iter, header_.block_size);
+ return data;
+ }
+ }();
+ op.compression = compression_;
+ op.data_length = static_cast<uint16_t>(data.size());
+
+ if (!WriteOperation(op, data.data(), data.size())) {
+ PLOG(ERROR) << "AddRawBlocks: write failed";
+ return false;
+ }
+ } else {
+ op.data_length = static_cast<uint16_t>(header_.block_size);
+ if (!WriteOperation(op, iter, header_.block_size)) {
+ PLOG(ERROR) << "AddRawBlocks: write failed";
+ return false;
+ }
+ }
+ iter += header_.block_size;
+
+ i += 1;
+ pending_blocks -= 1;
+ }
+
+ CHECK(pending_blocks == 0);
+ }
+ return true;
+}
+
+bool CowWriterV2::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
+ CHECK(!merge_in_progress_);
+ for (uint64_t i = 0; i < num_blocks; i++) {
+ CowOperation op = {};
+ op.type = kCowZeroOp;
+ op.new_block = new_block_start + i;
+ op.source = 0;
+ WriteOperation(op);
+ }
+ return true;
+}
+
+bool CowWriterV2::EmitLabel(uint64_t label) {
+ CHECK(!merge_in_progress_);
+ CowOperation op = {};
+ op.type = kCowLabelOp;
+ op.source = label;
+ return WriteOperation(op) && Sync();
+}
+
+bool CowWriterV2::EmitSequenceData(size_t num_ops, const uint32_t* data) {
+ CHECK(!merge_in_progress_);
+ size_t to_add = 0;
+ size_t max_ops = (header_.block_size * 2) / sizeof(uint32_t);
+ while (num_ops > 0) {
+ CowOperation op = {};
+ op.type = kCowSequenceOp;
+ op.source = next_data_pos_;
+ to_add = std::min(num_ops, max_ops);
+ op.data_length = static_cast<uint16_t>(to_add * sizeof(uint32_t));
+ if (!WriteOperation(op, data, op.data_length)) {
+ PLOG(ERROR) << "AddSequenceData: write failed";
+ return false;
+ }
+ num_ops -= to_add;
+ data += to_add;
+ }
+ return true;
+}
+
+bool CowWriterV2::EmitCluster() {
+ CowOperation op = {};
+ op.type = kCowClusterOp;
+ // Next cluster starts after remainder of current cluster and the next data block.
+ op.source = current_data_size_ + cluster_size_ - current_cluster_size_ - sizeof(CowOperation);
+ return WriteOperation(op);
+}
+
+bool CowWriterV2::EmitClusterIfNeeded() {
+ // If there isn't room for another op and the cluster end op, end the current cluster
+ if (cluster_size_ && cluster_size_ < current_cluster_size_ + 2 * sizeof(CowOperation)) {
+ if (!EmitCluster()) return false;
+ }
+ return true;
+}
+
+bool CowWriterV2::Finalize() {
+ if (!FlushCluster()) {
+ LOG(ERROR) << "Finalize: FlushCluster() failed";
+ return false;
+ }
+
+ auto continue_cluster_size = current_cluster_size_;
+ auto continue_data_size = current_data_size_;
+ auto continue_data_pos = next_data_pos_;
+ auto continue_op_pos = next_op_pos_;
+ auto continue_num_ops = footer_.op.num_ops;
+ bool extra_cluster = false;
+
+ // Blank out extra ops, in case we're in append mode and dropped ops.
+ if (cluster_size_) {
+ auto unused_cluster_space = cluster_size_ - current_cluster_size_;
+ std::string clr;
+ clr.resize(unused_cluster_space, '\0');
+ if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
+ PLOG(ERROR) << "Failed to seek to footer position.";
+ return false;
+ }
+ if (!android::base::WriteFully(fd_, clr.data(), clr.size())) {
+ PLOG(ERROR) << "clearing unused cluster area failed";
+ return false;
+ }
+ }
+
+ // Footer should be at the end of a file, so if there is data after the current block, end it
+ // and start a new cluster.
+ if (cluster_size_ && current_data_size_ > 0) {
+ EmitCluster();
+ extra_cluster = true;
+ }
+
+ footer_.op.ops_size = footer_.op.num_ops * sizeof(CowOperation);
+ if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
+ PLOG(ERROR) << "Failed to seek to footer position.";
+ return false;
+ }
+ memset(&footer_.unused, 0, sizeof(footer_.unused));
+
+ // Write out footer at end of file
+ if (!android::base::WriteFully(fd_, reinterpret_cast<const uint8_t*>(&footer_),
+ sizeof(footer_))) {
+ PLOG(ERROR) << "write footer failed";
+ return false;
+ }
+
+ // Remove excess data, if we're in append mode and threw away more data
+ // than we wrote before.
+ off_t offs = lseek(fd_.get(), 0, SEEK_CUR);
+ if (offs < 0) {
+ PLOG(ERROR) << "Failed to lseek to find current position";
+ return false;
+ }
+ if (!Truncate(offs)) {
+ return false;
+ }
+
+ // Reposition for additional Writing
+ if (extra_cluster) {
+ current_cluster_size_ = continue_cluster_size;
+ current_data_size_ = continue_data_size;
+ next_data_pos_ = continue_data_pos;
+ next_op_pos_ = continue_op_pos;
+ footer_.op.num_ops = continue_num_ops;
+ }
+
+ FlushCluster();
+
+ return Sync();
+}
+
+uint64_t CowWriterV2::GetCowSize() {
+ if (current_data_size_ > 0) {
+ return next_data_pos_ + sizeof(footer_);
+ } else {
+ return next_op_pos_ + sizeof(footer_);
+ }
+}
+
+bool CowWriterV2::GetDataPos(uint64_t* pos) {
+ off_t offs = lseek(fd_.get(), 0, SEEK_CUR);
+ if (offs < 0) {
+ PLOG(ERROR) << "lseek failed";
+ return false;
+ }
+ *pos = offs;
+ return true;
+}
+
+bool CowWriterV2::EnsureSpaceAvailable(const uint64_t bytes_needed) const {
+ if (bytes_needed > cow_image_size_) {
+ LOG(ERROR) << "No space left on COW device. Required: " << bytes_needed
+ << ", available: " << cow_image_size_;
+ errno = ENOSPC;
+ return false;
+ }
+ return true;
+}
+
+bool CowWriterV2::FlushCluster() {
+ ssize_t ret;
+
+ if (op_vec_index_) {
+ ret = pwritev(fd_.get(), cowop_vec_.get(), op_vec_index_, current_op_pos_);
+ if (ret != (op_vec_index_ * sizeof(CowOperation))) {
+ PLOG(ERROR) << "pwritev failed for CowOperation. Expected: "
+ << (op_vec_index_ * sizeof(CowOperation));
+ return false;
+ }
+ }
+
+ if (data_vec_index_) {
+ ret = pwritev(fd_.get(), data_vec_.get(), data_vec_index_, current_data_pos_);
+ if (ret != total_data_written_) {
+ PLOG(ERROR) << "pwritev failed for data. Expected: " << total_data_written_;
+ return false;
+ }
+ }
+
+ total_data_written_ = 0;
+ op_vec_index_ = 0;
+ data_vec_index_ = 0;
+ current_op_pos_ = next_op_pos_;
+ current_data_pos_ = next_data_pos_;
+
+ return true;
+}
+
+bool CowWriterV2::WriteOperation(const CowOperation& op, const void* data, size_t size) {
+ if (!EnsureSpaceAvailable(next_op_pos_ + sizeof(op))) {
+ return false;
+ }
+ if (!EnsureSpaceAvailable(next_data_pos_ + size)) {
+ return false;
+ }
+
+ if (batch_write_) {
+ CowOperation* cow_op = reinterpret_cast<CowOperation*>(cowop_vec_[op_vec_index_].iov_base);
+ std::memcpy(cow_op, &op, sizeof(CowOperation));
+ op_vec_index_ += 1;
+
+ if (data != nullptr && size > 0) {
+ struct iovec* data_ptr = data_vec_.get();
+ std::memcpy(data_ptr[data_vec_index_].iov_base, data, size);
+ data_ptr[data_vec_index_].iov_len = size;
+ data_vec_index_ += 1;
+ total_data_written_ += size;
+ }
+ } else {
+ if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek failed for writing operation.";
+ return false;
+ }
+ if (!android::base::WriteFully(fd_, reinterpret_cast<const uint8_t*>(&op), sizeof(op))) {
+ return false;
+ }
+ if (data != nullptr && size > 0) {
+ if (!WriteRawData(data, size)) return false;
+ }
+ }
+
+ AddOperation(op);
+
+ if (batch_write_) {
+ if (op_vec_index_ == header_.cluster_ops || data_vec_index_ == header_.cluster_ops ||
+ op.type == kCowLabelOp || op.type == kCowClusterOp) {
+ if (!FlushCluster()) {
+ LOG(ERROR) << "Failed to flush cluster data";
+ return false;
+ }
+ }
+ }
+
+ return EmitClusterIfNeeded();
+}
+
+void CowWriterV2::AddOperation(const CowOperation& op) {
+ footer_.op.num_ops++;
+
+ if (op.type == kCowClusterOp) {
+ current_cluster_size_ = 0;
+ current_data_size_ = 0;
+ } else if (header_.cluster_ops) {
+ current_cluster_size_ += sizeof(op);
+ current_data_size_ += op.data_length;
+ }
+
+ next_data_pos_ += op.data_length + GetNextDataOffset(op, header_.cluster_ops);
+ next_op_pos_ += sizeof(CowOperation) + GetNextOpOffset(op, header_.cluster_ops);
+}
+
+bool CowWriterV2::WriteRawData(const void* data, const size_t size) {
+ if (!android::base::WriteFullyAtOffset(fd_, data, size, next_data_pos_)) {
+ return false;
+ }
+ return true;
+}
+
+bool CowWriterV2::Sync() {
+ if (is_dev_null_) {
+ return true;
+ }
+ if (fsync(fd_.get()) < 0) {
+ PLOG(ERROR) << "fsync failed";
+ return false;
+ }
+ return true;
+}
+
+bool CowWriterV2::Truncate(off_t length) {
+ if (is_dev_null_ || is_block_device_) {
+ return true;
+ }
+ if (ftruncate(fd_.get(), length) < 0) {
+ PLOG(ERROR) << "Failed to truncate.";
+ return false;
+ }
+ return true;
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h
new file mode 100644
index 0000000..809ae57
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.h
@@ -0,0 +1,94 @@
+// 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 "writer_base.h"
+
+namespace android {
+namespace snapshot {
+
+class CowWriterV2 : public CowWriterBase {
+ public:
+ explicit CowWriterV2(const CowOptions& options, android::base::unique_fd&& fd);
+ ~CowWriterV2() override;
+
+ bool Initialize(std::optional<uint64_t> label = {}) override;
+ bool Finalize() override;
+ uint64_t GetCowSize() override;
+
+ protected:
+ virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
+ virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
+ virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
+ uint32_t old_block, uint16_t offset) override;
+ virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
+ virtual bool EmitLabel(uint64_t label) override;
+ virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
+
+ private:
+ bool EmitCluster();
+ bool EmitClusterIfNeeded();
+ bool EmitBlocks(uint64_t new_block_start, const void* data, size_t size, uint64_t old_block,
+ uint16_t offset, uint8_t type);
+ void SetupHeaders();
+ void SetupWriteOptions();
+ bool ParseOptions();
+ bool OpenForWrite();
+ bool OpenForAppend(uint64_t label);
+ bool GetDataPos(uint64_t* pos);
+ bool WriteRawData(const void* data, size_t size);
+ bool WriteOperation(const CowOperation& op, const void* data = nullptr, size_t size = 0);
+ void AddOperation(const CowOperation& op);
+ void InitPos();
+ void InitBatchWrites();
+ void InitWorkers();
+ bool FlushCluster();
+
+ bool CompressBlocks(size_t num_blocks, const void* data);
+ bool Sync();
+ bool Truncate(off_t length);
+ bool EnsureSpaceAvailable(const uint64_t bytes_needed) const;
+
+ private:
+ CowFooter footer_{};
+ CowCompressionAlgorithm compression_ = kCowCompressNone;
+ uint64_t current_op_pos_ = 0;
+ uint64_t next_op_pos_ = 0;
+ uint64_t next_data_pos_ = 0;
+ uint64_t current_data_pos_ = 0;
+ ssize_t total_data_written_ = 0;
+ uint32_t cluster_size_ = 0;
+ uint32_t current_cluster_size_ = 0;
+ uint64_t current_data_size_ = 0;
+ bool merge_in_progress_ = false;
+
+ int num_compress_threads_ = 1;
+ std::vector<std::unique_ptr<CompressWorker>> compress_threads_;
+ std::vector<std::future<bool>> threads_;
+ std::vector<std::basic_string<uint8_t>> compressed_buf_;
+ std::vector<std::basic_string<uint8_t>>::iterator buf_iter_;
+
+ std::vector<std::unique_ptr<CowOperation>> opbuffer_vec_;
+ std::vector<std::unique_ptr<uint8_t[]>> databuffer_vec_;
+ std::unique_ptr<struct iovec[]> cowop_vec_;
+ int op_vec_index_ = 0;
+
+ std::unique_ptr<struct iovec[]> data_vec_;
+ int data_vec_index_ = 0;
+ bool batch_write_ = false;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/make_cow_from_ab_ota.cpp b/fs_mgr/libsnapshot/make_cow_from_ab_ota.cpp
deleted file mode 100644
index 6a5754d..0000000
--- a/fs_mgr/libsnapshot/make_cow_from_ab_ota.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-//
-// Copyright (C) 2020 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 <arpa/inet.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <limits>
-#include <string>
-#include <unordered_set>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <bsdiff/bspatch.h>
-#include <bzlib.h>
-#include <gflags/gflags.h>
-#include <libsnapshot/cow_writer.h>
-#include <puffin/puffpatch.h>
-#include <sparse/sparse.h>
-#include <update_engine/update_metadata.pb.h>
-#include <xz.h>
-#include <ziparchive/zip_archive.h>
-
-namespace android {
-namespace snapshot {
-
-using android::base::borrowed_fd;
-using android::base::unique_fd;
-using chromeos_update_engine::DeltaArchiveManifest;
-using chromeos_update_engine::Extent;
-using chromeos_update_engine::InstallOperation;
-using chromeos_update_engine::PartitionUpdate;
-
-static constexpr uint64_t kBlockSize = 4096;
-
-DEFINE_string(source_tf, "", "Source target files (dir or zip file) for incremental payloads");
-DEFINE_string(compression, "gz", "Compression type to use (none or gz)");
-DEFINE_uint32(cluster_ops, 0, "Number of Cow Ops per cluster (0 or >1)");
-
-void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
- unsigned int, const char* message) {
- if (severity == android::base::ERROR) {
- fprintf(stderr, "%s\n", message);
- } else {
- fprintf(stdout, "%s\n", message);
- }
-}
-
-uint64_t ToLittleEndian(uint64_t value) {
- union {
- uint64_t u64;
- char bytes[8];
- } packed;
- packed.u64 = value;
- std::swap(packed.bytes[0], packed.bytes[7]);
- std::swap(packed.bytes[1], packed.bytes[6]);
- std::swap(packed.bytes[2], packed.bytes[5]);
- std::swap(packed.bytes[3], packed.bytes[4]);
- return packed.u64;
-}
-
-class PayloadConverter final {
- public:
- PayloadConverter(const std::string& in_file, const std::string& out_dir)
- : in_file_(in_file), out_dir_(out_dir), source_tf_zip_(nullptr, &CloseArchive) {}
-
- bool Run();
-
- private:
- bool OpenPayload();
- bool OpenSourceTargetFiles();
- bool ProcessPartition(const PartitionUpdate& update);
- bool ProcessOperation(const InstallOperation& op);
- bool ProcessZero(const InstallOperation& op);
- bool ProcessCopy(const InstallOperation& op);
- bool ProcessReplace(const InstallOperation& op);
- bool ProcessDiff(const InstallOperation& op);
- borrowed_fd OpenSourceImage();
-
- std::string in_file_;
- std::string out_dir_;
- unique_fd in_fd_;
- uint64_t payload_offset_ = 0;
- DeltaArchiveManifest manifest_;
- std::unordered_set<std::string> dap_;
- unique_fd source_tf_fd_;
- std::unique_ptr<ZipArchive, decltype(&CloseArchive)> source_tf_zip_;
-
- // Updated during ProcessPartition().
- std::string partition_name_;
- std::unique_ptr<CowWriter> writer_;
- unique_fd source_image_;
-};
-
-bool PayloadConverter::Run() {
- if (!OpenPayload()) {
- return false;
- }
-
- if (manifest_.has_dynamic_partition_metadata()) {
- const auto& dpm = manifest_.dynamic_partition_metadata();
- for (const auto& group : dpm.groups()) {
- for (const auto& partition : group.partition_names()) {
- dap_.emplace(partition);
- }
- }
- }
-
- if (dap_.empty()) {
- LOG(ERROR) << "No dynamic partitions found.";
- return false;
- }
-
- if (!OpenSourceTargetFiles()) {
- return false;
- }
-
- for (const auto& update : manifest_.partitions()) {
- if (!ProcessPartition(update)) {
- return false;
- }
- writer_ = nullptr;
- source_image_.reset();
- }
- return true;
-}
-
-bool PayloadConverter::OpenSourceTargetFiles() {
- if (FLAGS_source_tf.empty()) {
- return true;
- }
-
- source_tf_fd_.reset(open(FLAGS_source_tf.c_str(), O_RDONLY));
- if (source_tf_fd_ < 0) {
- LOG(ERROR) << "open failed: " << FLAGS_source_tf;
- return false;
- }
-
- struct stat s;
- if (fstat(source_tf_fd_.get(), &s) < 0) {
- LOG(ERROR) << "fstat failed: " << FLAGS_source_tf;
- return false;
- }
- if (S_ISDIR(s.st_mode)) {
- return true;
- }
-
- // Otherwise, assume it's a zip file.
- ZipArchiveHandle handle;
- if (OpenArchiveFd(source_tf_fd_.get(), FLAGS_source_tf.c_str(), &handle, false)) {
- LOG(ERROR) << "Could not open " << FLAGS_source_tf << " as a zip archive.";
- return false;
- }
- source_tf_zip_.reset(handle);
- return true;
-}
-
-bool PayloadConverter::ProcessPartition(const PartitionUpdate& update) {
- auto partition_name = update.partition_name();
- if (dap_.find(partition_name) == dap_.end()) {
- // Skip non-DAP partitions.
- return true;
- }
-
- auto path = out_dir_ + "/" + partition_name + ".cow";
- unique_fd fd(open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644));
- if (fd < 0) {
- PLOG(ERROR) << "open failed: " << path;
- return false;
- }
-
- CowOptions options;
- options.block_size = kBlockSize;
- options.compression = FLAGS_compression;
- options.cluster_ops = FLAGS_cluster_ops;
-
- writer_ = std::make_unique<CowWriter>(options);
- if (!writer_->Initialize(std::move(fd))) {
- LOG(ERROR) << "Unable to initialize COW writer";
- return false;
- }
-
- partition_name_ = partition_name;
-
- for (const auto& op : update.operations()) {
- if (!ProcessOperation(op)) {
- return false;
- }
- }
-
- if (!writer_->Finalize()) {
- LOG(ERROR) << "Unable to finalize COW for " << partition_name;
- return false;
- }
- return true;
-}
-
-bool PayloadConverter::ProcessOperation(const InstallOperation& op) {
- switch (op.type()) {
- case InstallOperation::SOURCE_COPY:
- return ProcessCopy(op);
- case InstallOperation::BROTLI_BSDIFF:
- case InstallOperation::PUFFDIFF:
- return ProcessDiff(op);
- case InstallOperation::REPLACE:
- case InstallOperation::REPLACE_XZ:
- case InstallOperation::REPLACE_BZ:
- return ProcessReplace(op);
- case InstallOperation::ZERO:
- return ProcessZero(op);
- default:
- LOG(ERROR) << "Unsupported op: " << (int)op.type();
- return false;
- }
- return true;
-}
-
-bool PayloadConverter::ProcessZero(const InstallOperation& op) {
- for (const auto& extent : op.dst_extents()) {
- if (!writer_->AddZeroBlocks(extent.start_block(), extent.num_blocks())) {
- LOG(ERROR) << "Could not add zero operation";
- return false;
- }
- }
- return true;
-}
-
-template <typename T>
-static uint64_t SizeOfAllExtents(const T& extents) {
- uint64_t total = 0;
- for (const auto& extent : extents) {
- total += extent.num_blocks() * kBlockSize;
- }
- return total;
-}
-
-class PuffInputStream final : public puffin::StreamInterface {
- public:
- PuffInputStream(uint8_t* buffer, size_t length) : buffer_(buffer), length_(length), pos_(0) {}
-
- bool GetSize(uint64_t* size) const override {
- *size = length_;
- return true;
- }
- bool GetOffset(uint64_t* offset) const override {
- *offset = pos_;
- return true;
- }
- bool Seek(uint64_t offset) override {
- if (offset > length_) return false;
- pos_ = offset;
- return true;
- }
- bool Read(void* buffer, size_t length) override {
- if (length_ - pos_ < length) return false;
- memcpy(buffer, buffer_ + pos_, length);
- pos_ += length;
- return true;
- }
- bool Write(const void*, size_t) override { return false; }
- bool Close() override { return true; }
-
- private:
- uint8_t* buffer_;
- size_t length_;
- size_t pos_;
-};
-
-class PuffOutputStream final : public puffin::StreamInterface {
- public:
- PuffOutputStream(std::vector<uint8_t>& stream) : stream_(stream), pos_(0) {}
-
- bool GetSize(uint64_t* size) const override {
- *size = stream_.size();
- return true;
- }
- bool GetOffset(uint64_t* offset) const override {
- *offset = pos_;
- return true;
- }
- bool Seek(uint64_t offset) override {
- if (offset > stream_.size()) {
- return false;
- }
- pos_ = offset;
- return true;
- }
- bool Read(void* buffer, size_t length) override {
- if (stream_.size() - pos_ < length) {
- return false;
- }
- memcpy(buffer, &stream_[0] + pos_, length);
- pos_ += length;
- return true;
- }
- bool Write(const void* buffer, size_t length) override {
- auto remaining = stream_.size() - pos_;
- if (remaining < length) {
- stream_.resize(stream_.size() + (length - remaining));
- }
- memcpy(&stream_[0] + pos_, buffer, length);
- pos_ += length;
- return true;
- }
- bool Close() override { return true; }
-
- private:
- std::vector<uint8_t>& stream_;
- size_t pos_;
-};
-
-bool PayloadConverter::ProcessDiff(const InstallOperation& op) {
- auto source_image = OpenSourceImage();
- if (source_image < 0) {
- return false;
- }
-
- uint64_t src_length = SizeOfAllExtents(op.src_extents());
- auto src = std::make_unique<uint8_t[]>(src_length);
- size_t src_pos = 0;
-
- // Read source bytes.
- for (const auto& extent : op.src_extents()) {
- uint64_t offset = extent.start_block() * kBlockSize;
- if (lseek(source_image.get(), offset, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek source image failed";
- return false;
- }
-
- uint64_t size = extent.num_blocks() * kBlockSize;
- CHECK(src_length - src_pos >= size);
- if (!android::base::ReadFully(source_image, src.get() + src_pos, size)) {
- PLOG(ERROR) << "read source image failed";
- return false;
- }
- src_pos += size;
- }
- CHECK(src_pos == src_length);
-
- // Read patch bytes.
- auto patch = std::make_unique<uint8_t[]>(op.data_length());
- if (lseek(in_fd_.get(), payload_offset_ + op.data_offset(), SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek payload failed";
- return false;
- }
- if (!android::base::ReadFully(in_fd_, patch.get(), op.data_length())) {
- PLOG(ERROR) << "read payload failed";
- return false;
- }
-
- std::vector<uint8_t> dest(SizeOfAllExtents(op.dst_extents()));
-
- // Apply the diff.
- if (op.type() == InstallOperation::BROTLI_BSDIFF) {
- size_t dest_pos = 0;
- auto sink = [&](const uint8_t* data, size_t length) -> size_t {
- CHECK(dest.size() - dest_pos >= length);
- memcpy(&dest[dest_pos], data, length);
- dest_pos += length;
- return length;
- };
- if (int rv = bsdiff::bspatch(src.get(), src_pos, patch.get(), op.data_length(), sink)) {
- LOG(ERROR) << "bspatch failed, error code " << rv;
- return false;
- }
- } else if (op.type() == InstallOperation::PUFFDIFF) {
- auto src_stream = std::make_unique<PuffInputStream>(src.get(), src_length);
- auto dest_stream = std::make_unique<PuffOutputStream>(dest);
- bool ok = PuffPatch(std::move(src_stream), std::move(dest_stream), patch.get(),
- op.data_length());
- if (!ok) {
- LOG(ERROR) << "puffdiff operation failed to apply";
- return false;
- }
- } else {
- LOG(ERROR) << "unsupported diff operation: " << op.type();
- return false;
- }
-
- // Write the final blocks to the COW.
- size_t dest_pos = 0;
- for (const auto& extent : op.dst_extents()) {
- uint64_t size = extent.num_blocks() * kBlockSize;
- CHECK(dest.size() - dest_pos >= size);
-
- if (!writer_->AddRawBlocks(extent.start_block(), &dest[dest_pos], size)) {
- return false;
- }
- dest_pos += size;
- }
- return true;
-}
-
-borrowed_fd PayloadConverter::OpenSourceImage() {
- if (source_image_ >= 0) {
- return source_image_;
- }
-
- unique_fd unzip_fd;
-
- auto local_path = "IMAGES/" + partition_name_ + ".img";
- if (source_tf_zip_) {
- {
- TemporaryFile tmp;
- if (tmp.fd < 0) {
- PLOG(ERROR) << "mkstemp failed";
- return -1;
- }
- unzip_fd.reset(tmp.release());
- }
-
- ZipEntry64 entry;
- if (FindEntry(source_tf_zip_.get(), local_path, &entry)) {
- LOG(ERROR) << "not found in archive: " << local_path;
- return -1;
- }
- if (ExtractEntryToFile(source_tf_zip_.get(), &entry, unzip_fd.get())) {
- LOG(ERROR) << "could not extract " << local_path;
- return -1;
- }
- if (lseek(unzip_fd.get(), 0, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek failed";
- return -1;
- }
- } else if (source_tf_fd_ >= 0) {
- unzip_fd.reset(openat(source_tf_fd_.get(), local_path.c_str(), O_RDONLY));
- if (unzip_fd < 0) {
- PLOG(ERROR) << "open failed: " << FLAGS_source_tf << "/" << local_path;
- return -1;
- }
- } else {
- LOG(ERROR) << "No source target files package was specified; need -source_tf";
- return -1;
- }
-
- std::unique_ptr<struct sparse_file, decltype(&sparse_file_destroy)> s(
- sparse_file_import(unzip_fd.get(), false, false), &sparse_file_destroy);
- if (s) {
- TemporaryFile tmp;
- if (tmp.fd < 0) {
- PLOG(ERROR) << "mkstemp failed";
- return -1;
- }
- if (sparse_file_write(s.get(), tmp.fd, false, false, false) < 0) {
- LOG(ERROR) << "sparse_file_write failed";
- return -1;
- }
- source_image_.reset(tmp.release());
- } else {
- source_image_ = std::move(unzip_fd);
- }
- return source_image_;
-}
-
-template <typename ContainerType>
-class ExtentIter final {
- public:
- ExtentIter(const ContainerType& container)
- : iter_(container.cbegin()), end_(container.cend()), dst_index_(0) {}
-
- bool GetNext(uint64_t* block) {
- while (iter_ != end_) {
- if (dst_index_ < iter_->num_blocks()) {
- break;
- }
- iter_++;
- dst_index_ = 0;
- }
- if (iter_ == end_) {
- return false;
- }
- *block = iter_->start_block() + dst_index_;
- dst_index_++;
- return true;
- }
-
- private:
- typename ContainerType::const_iterator iter_;
- typename ContainerType::const_iterator end_;
- uint64_t dst_index_;
-};
-
-bool PayloadConverter::ProcessCopy(const InstallOperation& op) {
- ExtentIter dst_blocks(op.dst_extents());
-
- for (const auto& extent : op.src_extents()) {
- for (uint64_t i = 0; i < extent.num_blocks(); i++) {
- uint64_t src_block = extent.start_block() + i;
- uint64_t dst_block;
- if (!dst_blocks.GetNext(&dst_block)) {
- LOG(ERROR) << "SOURCE_COPY contained mismatching extents";
- return false;
- }
- if (src_block == dst_block) continue;
- if (!writer_->AddCopy(dst_block, src_block)) {
- LOG(ERROR) << "Could not add copy operation";
- return false;
- }
- }
- }
- return true;
-}
-
-bool PayloadConverter::ProcessReplace(const InstallOperation& op) {
- auto buffer_size = op.data_length();
- auto buffer = std::make_unique<char[]>(buffer_size);
- uint64_t offs = payload_offset_ + op.data_offset();
- if (lseek(in_fd_.get(), offs, SEEK_SET) < 0) {
- PLOG(ERROR) << "lseek " << offs << " failed";
- return false;
- }
- if (!android::base::ReadFully(in_fd_, buffer.get(), buffer_size)) {
- PLOG(ERROR) << "read " << buffer_size << " bytes from offset " << offs << "failed";
- return false;
- }
-
- uint64_t dst_size = 0;
- for (const auto& extent : op.dst_extents()) {
- dst_size += extent.num_blocks() * kBlockSize;
- }
-
- if (op.type() == InstallOperation::REPLACE_BZ) {
- auto tmp = std::make_unique<char[]>(dst_size);
-
- uint32_t actual_size;
- if (dst_size > std::numeric_limits<typeof(actual_size)>::max()) {
- LOG(ERROR) << "too many bytes to decompress: " << dst_size;
- return false;
- }
- actual_size = static_cast<uint32_t>(dst_size);
-
- auto rv = BZ2_bzBuffToBuffDecompress(tmp.get(), &actual_size, buffer.get(), buffer_size, 0,
- 0);
- if (rv) {
- LOG(ERROR) << "bz2 decompress failed: " << rv;
- return false;
- }
- if (actual_size != dst_size) {
- LOG(ERROR) << "bz2 returned " << actual_size << " bytes, expected " << dst_size;
- return false;
- }
- buffer = std::move(tmp);
- buffer_size = dst_size;
- } else if (op.type() == InstallOperation::REPLACE_XZ) {
- constexpr uint32_t kXzMaxDictSize = 64 * 1024 * 1024;
-
- if (dst_size > std::numeric_limits<size_t>::max()) {
- LOG(ERROR) << "too many bytes to decompress: " << dst_size;
- return false;
- }
-
- std::unique_ptr<struct xz_dec, decltype(&xz_dec_end)> s(
- xz_dec_init(XZ_DYNALLOC, kXzMaxDictSize), xz_dec_end);
- if (!s) {
- LOG(ERROR) << "xz_dec_init failed";
- return false;
- }
-
- auto tmp = std::make_unique<char[]>(dst_size);
-
- struct xz_buf args;
- args.in = reinterpret_cast<const uint8_t*>(buffer.get());
- args.in_pos = 0;
- args.in_size = buffer_size;
- args.out = reinterpret_cast<uint8_t*>(tmp.get());
- args.out_pos = 0;
- args.out_size = dst_size;
-
- auto rv = xz_dec_run(s.get(), &args);
- if (rv != XZ_STREAM_END) {
- LOG(ERROR) << "xz decompress failed: " << (int)rv;
- return false;
- }
- buffer = std::move(tmp);
- buffer_size = dst_size;
- }
-
- uint64_t buffer_pos = 0;
- for (const auto& extent : op.dst_extents()) {
- uint64_t extent_size = extent.num_blocks() * kBlockSize;
- if (buffer_size - buffer_pos < extent_size) {
- LOG(ERROR) << "replace op ran out of input buffer";
- return false;
- }
- if (!writer_->AddRawBlocks(extent.start_block(), buffer.get() + buffer_pos, extent_size)) {
- LOG(ERROR) << "failed to add raw blocks from replace op";
- return false;
- }
- buffer_pos += extent_size;
- }
- return true;
-}
-
-bool PayloadConverter::OpenPayload() {
- in_fd_.reset(open(in_file_.c_str(), O_RDONLY));
- if (in_fd_ < 0) {
- PLOG(ERROR) << "open " << in_file_;
- return false;
- }
-
- char magic[4];
- if (!android::base::ReadFully(in_fd_, magic, sizeof(magic))) {
- PLOG(ERROR) << "read magic";
- return false;
- }
- if (std::string(magic, sizeof(magic)) != "CrAU") {
- LOG(ERROR) << "Invalid magic in " << in_file_;
- return false;
- }
-
- uint64_t version;
- uint64_t manifest_size;
- uint32_t manifest_signature_size = 0;
- if (!android::base::ReadFully(in_fd_, &version, sizeof(version))) {
- PLOG(ERROR) << "read version";
- return false;
- }
- version = ToLittleEndian(version);
- if (version < 2) {
- LOG(ERROR) << "Only payload version 2 or higher is supported.";
- return false;
- }
-
- if (!android::base::ReadFully(in_fd_, &manifest_size, sizeof(manifest_size))) {
- PLOG(ERROR) << "read manifest_size";
- return false;
- }
- manifest_size = ToLittleEndian(manifest_size);
- if (!android::base::ReadFully(in_fd_, &manifest_signature_size,
- sizeof(manifest_signature_size))) {
- PLOG(ERROR) << "read manifest_signature_size";
- return false;
- }
- manifest_signature_size = ntohl(manifest_signature_size);
-
- auto manifest = std::make_unique<uint8_t[]>(manifest_size);
- if (!android::base::ReadFully(in_fd_, manifest.get(), manifest_size)) {
- PLOG(ERROR) << "read manifest";
- return false;
- }
-
- // Skip past manifest signature.
- auto offs = lseek(in_fd_, manifest_signature_size, SEEK_CUR);
- if (offs < 0) {
- PLOG(ERROR) << "lseek failed";
- return false;
- }
- payload_offset_ = offs;
-
- if (!manifest_.ParseFromArray(manifest.get(), manifest_size)) {
- LOG(ERROR) << "could not parse manifest";
- return false;
- }
- return true;
-}
-
-} // namespace snapshot
-} // namespace android
-
-int main(int argc, char** argv) {
- android::base::InitLogging(argv, android::snapshot::MyLogger);
- gflags::SetUsageMessage("Convert OTA payload to a Virtual A/B COW");
- int arg_start = gflags::ParseCommandLineFlags(&argc, &argv, false);
-
- xz_crc32_init();
-
- if (argc - arg_start != 2) {
- std::cerr << "Usage: [options] <payload.bin> <out-dir>\n";
- return 1;
- }
-
- android::snapshot::PayloadConverter pc(argv[arg_start], argv[arg_start + 1]);
- return pc.Run() ? 0 : 1;
-}
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.h b/fs_mgr/libsnapshot/partition_cow_creator.h
index 949e6c5..bd5c8cb 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.h
+++ b/fs_mgr/libsnapshot/partition_cow_creator.h
@@ -60,6 +60,12 @@
bool using_snapuserd = false;
std::string compression_algorithm;
+ // True if multi-threaded compression should be enabled
+ bool enable_threading;
+
+ // True if COW writes should be batched in memory
+ bool batched_writes;
+
struct Return {
SnapshotStatus snapshot_status;
std::vector<Interval> cow_partition_usable_regions;
diff --git a/fs_mgr/libsnapshot/power_test.cpp b/fs_mgr/libsnapshot/power_test.cpp
deleted file mode 100644
index 4d2548a..0000000
--- a/fs_mgr/libsnapshot/power_test.cpp
+++ /dev/null
@@ -1,559 +0,0 @@
-//
-// Copyright (C) 2020 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 <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <chrono>
-#include <iostream>
-#include <random>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/parsedouble.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <ext4_utils/ext4_utils.h>
-#include <fstab/fstab.h>
-#include <libdm/dm.h>
-#include <libfiemap/image_manager.h>
-
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-using android::base::borrowed_fd;
-using android::base::unique_fd;
-using android::dm::DeviceMapper;
-using android::dm::DmDeviceState;
-using android::dm::DmTable;
-using android::dm::DmTargetSnapshot;
-using android::dm::SnapshotStorageMode;
-using android::fiemap::ImageManager;
-using android::fs_mgr::Fstab;
-
-namespace android {
-namespace snapshot {
-
-static void usage() {
- std::cerr << "Usage:\n";
- std::cerr << " create <orig-payload> <new-payload>\n";
- std::cerr << "\n";
- std::cerr << " Create a snapshot device containing the contents of\n";
- std::cerr << " orig-payload, and then write the contents of new-payload.\n";
- std::cerr << " The original files are not modified.\n";
- std::cerr << "\n";
- std::cerr << " merge <fail-rate>\n";
- std::cerr << "\n";
- std::cerr << " Merge the snapshot previously started by create, and wait\n";
- std::cerr << " for it to complete. Once done, it is compared to the\n";
- std::cerr << " new-payload for consistency. The original files are not \n";
- std::cerr << " modified. If a fail-rate is passed (as a fraction between 0\n";
- std::cerr << " and 100), every 10ms the device has that percent change of\n";
- std::cerr << " injecting a kernel crash.\n";
- std::cerr << "\n";
- std::cerr << " check <new-payload>\n";
- std::cerr << " Verify that all artifacts are correct after a merge\n";
- std::cerr << " completes.\n";
- std::cerr << "\n";
- std::cerr << " cleanup\n";
- std::cerr << " Remove all ImageManager artifacts from create/merge.\n";
-}
-
-class PowerTest final {
- public:
- PowerTest();
- bool Run(int argc, char** argv);
-
- private:
- bool OpenImageManager();
- bool Create(int argc, char** argv);
- bool Merge(int argc, char** argv);
- bool Check(int argc, char** argv);
- bool Cleanup();
- bool CleanupImage(const std::string& name);
- bool SetupImages(const std::string& first_file, borrowed_fd second_fd);
- bool MapImages();
- bool MapSnapshot(SnapshotStorageMode mode);
- bool GetMergeStatus(DmTargetSnapshot::Status* status);
-
- static constexpr char kSnapshotName[] = "snapshot-power-test";
- static constexpr char kSnapshotImageName[] = "snapshot-power-test-image";
- static constexpr char kSnapshotCowName[] = "snapshot-power-test-cow";
-
- DeviceMapper& dm_;
- std::unique_ptr<ImageManager> images_;
- std::string image_path_;
- std::string cow_path_;
- std::string snapshot_path_;
-};
-
-PowerTest::PowerTest() : dm_(DeviceMapper::Instance()) {}
-
-bool PowerTest::Run([[maybe_unused]] int argc, [[maybe_unused]] char** argv) {
- if (!OpenImageManager()) {
- return false;
- }
-
- if (argc < 2) {
- usage();
- return false;
- }
- if (argv[1] == "create"s) {
- return Create(argc, argv);
- } else if (argv[1] == "merge"s) {
- return Merge(argc, argv);
- } else if (argv[1] == "check"s) {
- return Check(argc, argv);
- } else if (argv[1] == "cleanup"s) {
- return Cleanup();
- } else {
- usage();
- return false;
- }
-}
-
-bool PowerTest::OpenImageManager() {
- std::vector<std::string> dirs = {
- "/data/gsi/test",
- "/metadata/gsi/test",
- };
- for (const auto& dir : dirs) {
- if (mkdir(dir.c_str(), 0700) && errno != EEXIST) {
- std::cerr << "mkdir " << dir << ": " << strerror(errno) << "\n";
- return false;
- }
- }
-
- images_ = ImageManager::Open("/metadata/gsi/test", "/data/gsi/test");
- if (!images_) {
- std::cerr << "Could not open ImageManager\n";
- return false;
- }
- return true;
-}
-
-bool PowerTest::Create(int argc, char** argv) {
- if (argc < 4) {
- usage();
- return false;
- }
-
- std::string first = argv[2];
- std::string second = argv[3];
-
- unique_fd second_fd(open(second.c_str(), O_RDONLY));
- if (second_fd < 0) {
- std::cerr << "open " << second << ": " << strerror(errno) << "\n";
- return false;
- }
-
- if (!Cleanup()) {
- return false;
- }
- if (!SetupImages(first, second_fd)) {
- return false;
- }
- if (!MapSnapshot(SnapshotStorageMode::Persistent)) {
- return false;
- }
-
- struct stat s;
- if (fstat(second_fd, &s)) {
- std::cerr << "fstat " << second << ": " << strerror(errno) << "\n";
- return false;
- }
-
- unique_fd snap_fd(open(snapshot_path_.c_str(), O_WRONLY));
- if (snap_fd < 0) {
- std::cerr << "open " << snapshot_path_ << ": " << strerror(errno) << "\n";
- return false;
- }
-
- uint8_t chunk[4096];
- uint64_t written = 0;
- while (written < s.st_size) {
- uint64_t remaining = s.st_size - written;
- size_t bytes = (size_t)std::min((uint64_t)sizeof(chunk), remaining);
- if (!android::base::ReadFully(second_fd, chunk, bytes)) {
- std::cerr << "read " << second << ": " << strerror(errno) << "\n";
- return false;
- }
- if (!android::base::WriteFully(snap_fd, chunk, bytes)) {
- std::cerr << "write " << snapshot_path_ << ": " << strerror(errno) << "\n";
- return false;
- }
- written += bytes;
- }
- if (fsync(snap_fd)) {
- std::cerr << "fsync: " << strerror(errno) << "\n";
- return false;
- }
-
- sync();
-
- snap_fd = {};
- if (!dm_.DeleteDeviceIfExists(kSnapshotName)) {
- std::cerr << "could not delete dm device " << kSnapshotName << "\n";
- return false;
- }
- if (!images_->UnmapImageIfExists(kSnapshotImageName)) {
- std::cerr << "failed to unmap " << kSnapshotImageName << "\n";
- return false;
- }
- if (!images_->UnmapImageIfExists(kSnapshotCowName)) {
- std::cerr << "failed to unmap " << kSnapshotImageName << "\n";
- return false;
- }
- return true;
-}
-
-bool PowerTest::Cleanup() {
- if (!dm_.DeleteDeviceIfExists(kSnapshotName)) {
- std::cerr << "could not delete dm device " << kSnapshotName << "\n";
- return false;
- }
- if (!CleanupImage(kSnapshotImageName) || !CleanupImage(kSnapshotCowName)) {
- return false;
- }
- return true;
-}
-
-bool PowerTest::CleanupImage(const std::string& name) {
- if (!images_->UnmapImageIfExists(name)) {
- std::cerr << "failed to unmap " << name << "\n";
- return false;
- }
- if (images_->BackingImageExists(name) && !images_->DeleteBackingImage(name)) {
- std::cerr << "failed to delete " << name << "\n";
- return false;
- }
- return true;
-}
-
-bool PowerTest::SetupImages(const std::string& first, borrowed_fd second_fd) {
- unique_fd first_fd(open(first.c_str(), O_RDONLY));
- if (first_fd < 0) {
- std::cerr << "open " << first << ": " << strerror(errno) << "\n";
- return false;
- }
-
- struct stat s1, s2;
- if (fstat(first_fd.get(), &s1)) {
- std::cerr << "first stat: " << strerror(errno) << "\n";
- return false;
- }
- if (fstat(second_fd.get(), &s2)) {
- std::cerr << "second stat: " << strerror(errno) << "\n";
- return false;
- }
-
- // Pick the bigger size of both images, rounding up to the nearest block.
- uint64_t s1_size = (s1.st_size + 4095) & ~uint64_t(4095);
- uint64_t s2_size = (s2.st_size + 4095) & ~uint64_t(4095);
- uint64_t image_size = std::max(s1_size, s2_size) + (1024 * 1024 * 128);
- if (!images_->CreateBackingImage(kSnapshotImageName, image_size, 0, nullptr)) {
- std::cerr << "failed to create " << kSnapshotImageName << "\n";
- return false;
- }
- // Use the same size for the cow.
- if (!images_->CreateBackingImage(kSnapshotCowName, image_size, 0, nullptr)) {
- std::cerr << "failed to create " << kSnapshotCowName << "\n";
- return false;
- }
- if (!MapImages()) {
- return false;
- }
-
- unique_fd image_fd(open(image_path_.c_str(), O_WRONLY));
- if (image_fd < 0) {
- std::cerr << "open: " << image_path_ << ": " << strerror(errno) << "\n";
- return false;
- }
-
- uint8_t chunk[4096];
- uint64_t written = 0;
- while (written < s1.st_size) {
- uint64_t remaining = s1.st_size - written;
- size_t bytes = (size_t)std::min((uint64_t)sizeof(chunk), remaining);
- if (!android::base::ReadFully(first_fd, chunk, bytes)) {
- std::cerr << "read: " << strerror(errno) << "\n";
- return false;
- }
- if (!android::base::WriteFully(image_fd, chunk, bytes)) {
- std::cerr << "write: " << strerror(errno) << "\n";
- return false;
- }
- written += bytes;
- }
- if (fsync(image_fd)) {
- std::cerr << "fsync: " << strerror(errno) << "\n";
- return false;
- }
-
- // Zero the first block of the COW.
- unique_fd cow_fd(open(cow_path_.c_str(), O_WRONLY));
- if (cow_fd < 0) {
- std::cerr << "open: " << cow_path_ << ": " << strerror(errno) << "\n";
- return false;
- }
-
- memset(chunk, 0, sizeof(chunk));
- if (!android::base::WriteFully(cow_fd, chunk, sizeof(chunk))) {
- std::cerr << "read: " << strerror(errno) << "\n";
- return false;
- }
- if (fsync(cow_fd)) {
- std::cerr << "fsync: " << strerror(errno) << "\n";
- return false;
- }
- return true;
-}
-
-bool PowerTest::MapImages() {
- if (!images_->MapImageDevice(kSnapshotImageName, 10s, &image_path_)) {
- std::cerr << "failed to map " << kSnapshotImageName << "\n";
- return false;
- }
- if (!images_->MapImageDevice(kSnapshotCowName, 10s, &cow_path_)) {
- std::cerr << "failed to map " << kSnapshotCowName << "\n";
- return false;
- }
- return true;
-}
-
-bool PowerTest::MapSnapshot(SnapshotStorageMode mode) {
- uint64_t sectors;
- {
- unique_fd fd(open(image_path_.c_str(), O_RDONLY));
- if (fd < 0) {
- std::cerr << "open: " << image_path_ << ": " << strerror(errno) << "\n";
- return false;
- }
- sectors = get_block_device_size(fd) / 512;
- }
-
- DmTable table;
- table.Emplace<DmTargetSnapshot>(0, sectors, image_path_, cow_path_, mode, 8);
- if (!dm_.CreateDevice(kSnapshotName, table, &snapshot_path_, 10s)) {
- std::cerr << "failed to create snapshot device\n";
- return false;
- }
- return true;
-}
-
-bool PowerTest::GetMergeStatus(DmTargetSnapshot::Status* status) {
- std::vector<DeviceMapper::TargetInfo> targets;
- if (!dm_.GetTableStatus(kSnapshotName, &targets)) {
- std::cerr << "failed to get merge status\n";
- return false;
- }
- if (targets.size() != 1) {
- std::cerr << "merge device has wrong number of targets\n";
- return false;
- }
- if (!DmTargetSnapshot::ParseStatusText(targets[0].data, status)) {
- std::cerr << "could not parse merge target status text\n";
- return false;
- }
- return true;
-}
-
-static std::string GetUserdataBlockDeviceName() {
- Fstab fstab;
- if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
- return {};
- }
-
- auto entry = android::fs_mgr::GetEntryForMountPoint(&fstab, "/data");
- if (!entry) {
- return {};
- }
-
- auto prefix = "/dev/block/"s;
- if (!android::base::StartsWith(entry->blk_device, prefix)) {
- return {};
- }
- return entry->blk_device.substr(prefix.size());
-}
-
-bool PowerTest::Merge(int argc, char** argv) {
- // Start an f2fs GC to really stress things. :TODO: figure out data device
- auto userdata_dev = GetUserdataBlockDeviceName();
- if (userdata_dev.empty()) {
- std::cerr << "could not locate userdata block device\n";
- return false;
- }
-
- auto cmd =
- android::base::StringPrintf("echo 1 > /sys/fs/f2fs/%s/gc_urgent", userdata_dev.c_str());
- system(cmd.c_str());
-
- if (dm_.GetState(kSnapshotName) == DmDeviceState::INVALID) {
- if (!MapImages()) {
- return false;
- }
- if (!MapSnapshot(SnapshotStorageMode::Merge)) {
- return false;
- }
- }
-
- std::random_device r;
- std::default_random_engine re(r());
- std::uniform_real_distribution<double> dist(0.0, 100.0);
-
- std::optional<double> failure_rate;
- if (argc >= 3) {
- double d;
- if (!android::base::ParseDouble(argv[2], &d)) {
- std::cerr << "Could not parse failure rate as double: " << argv[2] << "\n";
- return false;
- }
- failure_rate = d;
- }
-
- while (true) {
- DmTargetSnapshot::Status status;
- if (!GetMergeStatus(&status)) {
- return false;
- }
- if (!status.error.empty()) {
- std::cerr << "merge reported error: " << status.error << "\n";
- return false;
- }
- if (status.sectors_allocated == status.metadata_sectors) {
- break;
- }
-
- std::cerr << status.sectors_allocated << " / " << status.metadata_sectors << "\n";
-
- if (failure_rate && *failure_rate >= dist(re)) {
- system("echo 1 > /proc/sys/kernel/sysrq");
- system("echo c > /proc/sysrq-trigger");
- }
-
- std::this_thread::sleep_for(10ms);
- }
-
- std::cout << "Merge completed.\n";
- return true;
-}
-
-bool PowerTest::Check([[maybe_unused]] int argc, [[maybe_unused]] char** argv) {
- if (argc < 3) {
- std::cerr << "Expected argument: <new-image-path>\n";
- return false;
- }
- std::string md_path, image_path;
- std::string canonical_path = argv[2];
-
- if (!dm_.GetDmDevicePathByName(kSnapshotName, &md_path)) {
- std::cerr << "could not get dm-path for merge device\n";
- return false;
- }
- if (!images_->GetMappedImageDevice(kSnapshotImageName, &image_path)) {
- std::cerr << "could not get image path\n";
- return false;
- }
-
- unique_fd md_fd(open(md_path.c_str(), O_RDONLY));
- if (md_fd < 0) {
- std::cerr << "open: " << md_path << ": " << strerror(errno) << "\n";
- return false;
- }
- unique_fd image_fd(open(image_path.c_str(), O_RDONLY));
- if (image_fd < 0) {
- std::cerr << "open: " << image_path << ": " << strerror(errno) << "\n";
- return false;
- }
- unique_fd canonical_fd(open(canonical_path.c_str(), O_RDONLY));
- if (canonical_fd < 0) {
- std::cerr << "open: " << canonical_path << ": " << strerror(errno) << "\n";
- return false;
- }
-
- struct stat s;
- if (fstat(canonical_fd, &s)) {
- std::cerr << "fstat: " << canonical_path << ": " << strerror(errno) << "\n";
- return false;
- }
- uint64_t canonical_size = s.st_size;
- uint64_t md_size = get_block_device_size(md_fd);
- uint64_t image_size = get_block_device_size(image_fd);
- if (image_size != md_size) {
- std::cerr << "image size does not match merge device size\n";
- return false;
- }
- if (canonical_size > image_size) {
- std::cerr << "canonical size " << canonical_size << " is greater than image size "
- << image_size << "\n";
- return false;
- }
-
- constexpr size_t kBlockSize = 4096;
- uint8_t canonical_buffer[kBlockSize];
- uint8_t image_buffer[kBlockSize];
- uint8_t md_buffer[kBlockSize];
-
- uint64_t remaining = canonical_size;
- uint64_t blockno = 0;
- while (remaining) {
- size_t bytes = (size_t)std::min((uint64_t)kBlockSize, remaining);
- if (!android::base::ReadFully(canonical_fd, canonical_buffer, bytes)) {
- std::cerr << "read: " << canonical_buffer << ": " << strerror(errno) << "\n";
- return false;
- }
- if (!android::base::ReadFully(image_fd, image_buffer, bytes)) {
- std::cerr << "read: " << image_buffer << ": " << strerror(errno) << "\n";
- return false;
- }
- if (!android::base::ReadFully(md_fd, md_buffer, bytes)) {
- std::cerr << "read: " << md_buffer << ": " << strerror(errno) << "\n";
- return false;
- }
- if (memcmp(canonical_buffer, image_buffer, bytes)) {
- std::cerr << "canonical and image differ at block " << blockno << "\n";
- return false;
- }
- if (memcmp(canonical_buffer, md_buffer, bytes)) {
- std::cerr << "canonical and image differ at block " << blockno << "\n";
- return false;
- }
-
- remaining -= bytes;
- blockno++;
- }
-
- std::cout << "Images all match.\n";
- return true;
-}
-
-} // namespace snapshot
-} // namespace android
-
-int main(int argc, char** argv) {
- android::snapshot::PowerTest test;
-
- if (!test.Run(argc, argv)) {
- std::cerr << "Unexpected error running test." << std::endl;
- return 1;
- }
- fflush(stdout);
- return 0;
-}
diff --git a/fs_mgr/libsnapshot/run_power_test.sh b/fs_mgr/libsnapshot/run_power_test.sh
deleted file mode 100755
index dc03dc9..0000000
--- a/fs_mgr/libsnapshot/run_power_test.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-set -e
-
-if [ -z "$FAIL_RATE" ]; then
- FAIL_RATE=5.0
-fi
-if [ ! -z "$ANDROID_SERIAL" ]; then
- DEVICE_ARGS=-s $ANDROID_SERIAL
-else
- DEVICE_ARGS=
-fi
-
-TEST_BIN=/data/nativetest64/snapshot_power_test/snapshot_power_test
-
-while :
-do
- adb $DEVICE_ARGS wait-for-device
- adb $DEVICE_ARGS root
- adb $DEVICE_ARGS shell rm $TEST_BIN
- adb $DEVICE_ARGS sync data
- set +e
- output=$(adb $DEVICE_ARGS shell $TEST_BIN merge $FAIL_RATE 2>&1)
- set -e
- if [[ "$output" == *"Merge completed"* ]]; then
- echo "Merge completed."
- break
- fi
- if [[ "$output" == *"Unexpected error"* ]]; then
- echo "Unexpected error."
- exit 1
- fi
-done
-
-adb $DEVICE_ARGS shell $TEST_BIN check $1
diff --git a/fs_mgr/libsnapshot/run_snapshot_tests.sh b/fs_mgr/libsnapshot/run_snapshot_tests.sh
deleted file mode 100644
index b03a4e0..0000000
--- a/fs_mgr/libsnapshot/run_snapshot_tests.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/system/bin/sh
-
-# Detect host or AOSP.
-getprop ro.build.version.sdk > /dev/null 2>&1
-if [ $? -eq 0 ]; then
- cmd_prefix=""
- local_root=""
-else
- cmd_prefix="adb shell"
- local_root="${ANDROID_PRODUCT_OUT}"
- set -e
- set -x
- adb root
- adb sync data
- set +x
- set +e
-fi
-
-testpath64="/data/nativetest64/vts_libsnapshot_test/vts_libsnapshot_test"
-testpath32="/data/nativetest/vts_libsnapshot_test/vts_libsnapshot_test"
-if [ -f "${local_root}/${testpath64}" ]; then
- testpath="${testpath64}"
-elif [ -f "${local_root}/${testpath32}" ]; then
- testpath="${testpath32}"
-else
- echo "ERROR: vts_libsnapshot_test not found." 1>&2
- echo "Make sure to build vts_libsnapshot_test or snapshot_tests first." 1>&2
- exit 1
-fi
-
-# Verbose, error on failure.
-set -x
-set -e
-
-time ${cmd_prefix} ${testpath}
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 6fed09c..fbea79b 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -45,9 +45,9 @@
#include <android/snapshot/snapshot.pb.h>
#include <libsnapshot/snapshot_stats.h>
#include "device_info.h"
+#include "libsnapshot_cow/parser_v2.h"
#include "partition_cow_creator.h"
#include "snapshot_metadata_updater.h"
-#include "snapshot_reader.h"
#include "utility.h"
namespace android {
@@ -400,6 +400,12 @@
status->set_metadata_sectors(0);
status->set_using_snapuserd(cow_creator->using_snapuserd);
status->set_compression_algorithm(cow_creator->compression_algorithm);
+ if (cow_creator->enable_threading) {
+ status->set_enable_threading(cow_creator->enable_threading);
+ }
+ if (cow_creator->batched_writes) {
+ status->set_batched_writes(cow_creator->batched_writes);
+ }
if (!WriteSnapshotStatus(lock, *status)) {
PLOG(ERROR) << "Could not write snapshot status: " << status->name();
@@ -1498,6 +1504,7 @@
if (UpdateUsesUserSnapshots(lock) && !device()->IsTestDevice()) {
if (snapuserd_client_) {
snapuserd_client_->DetachSnapuserd();
+ snapuserd_client_->RemoveTransitionedDaemonIndicator();
snapuserd_client_ = nullptr;
}
}
@@ -2894,6 +2901,20 @@
}
}
+std::ostream& operator<<(std::ostream& os, MergePhase phase) {
+ switch (phase) {
+ case MergePhase::NO_MERGE:
+ return os << "none";
+ case MergePhase::FIRST_PHASE:
+ return os << "first";
+ case MergePhase::SECOND_PHASE:
+ return os << "second";
+ default:
+ LOG(ERROR) << "Unknown merge phase: " << static_cast<uint32_t>(phase);
+ return os << "unknown(" << static_cast<uint32_t>(phase) << ")";
+ }
+}
+
UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock);
return status.state();
@@ -3112,6 +3133,7 @@
for (auto&& [name, status] : all_snapshot_status) {
sum += status.cow_file_size();
}
+ LOG(INFO) << "Calculated needed COW space: " << sum << " bytes";
return Return::NoSpace(sum);
}
@@ -3180,37 +3202,20 @@
CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME);
- std::map<std::string, SnapshotStatus> all_snapshot_status;
-
- // In case of error, automatically delete devices that are created along the way.
- // Note that "lock" is destroyed after "created_devices", so it is safe to use |lock| for
- // these devices.
- AutoDeviceList created_devices;
-
const auto& dap_metadata = manifest.dynamic_partition_metadata();
- CowOptions options;
- CowWriter writer(options);
- bool cow_format_support = true;
- if (dap_metadata.cow_version() < writer.GetCowVersion()) {
- cow_format_support = false;
- }
-
- LOG(INFO) << " dap_metadata.cow_version(): " << dap_metadata.cow_version()
- << " writer.GetCowVersion(): " << writer.GetCowVersion();
-
- // Deduce supported features.
- bool userspace_snapshots = CanUseUserspaceSnapshots();
- bool legacy_compression = GetLegacyCompressionEnabledProperty();
std::string vabc_disable_reason;
if (!dap_metadata.vabc_enabled()) {
vabc_disable_reason = "not enabled metadata";
} else if (device_->IsRecovery()) {
vabc_disable_reason = "recovery";
- } else if (!cow_format_support) {
- vabc_disable_reason = "cow format not supported";
+ } else if (!KernelSupportsCompressedSnapshots()) {
+ vabc_disable_reason = "kernel missing userspace block device support";
}
+ // Deduce supported features.
+ bool userspace_snapshots = CanUseUserspaceSnapshots();
+ bool legacy_compression = GetLegacyCompressionEnabledProperty();
if (!vabc_disable_reason.empty()) {
if (userspace_snapshots) {
LOG(INFO) << "Userspace snapshots disabled: " << vabc_disable_reason;
@@ -3222,6 +3227,16 @@
legacy_compression = false;
}
+ if (legacy_compression || userspace_snapshots) {
+ if (dap_metadata.cow_version() < kMinCowVersion ||
+ dap_metadata.cow_version() > kMaxCowVersion) {
+ LOG(ERROR) << "Manifest cow version is out of bounds (got: "
+ << dap_metadata.cow_version() << ", min: " << kMinCowVersion
+ << ", max: " << kMaxCowVersion << ")";
+ return Return::Error();
+ }
+ }
+
const bool using_snapuserd = userspace_snapshots || legacy_compression;
if (!using_snapuserd) {
LOG(INFO) << "Using legacy Virtual A/B (dm-snapshot)";
@@ -3247,10 +3262,24 @@
.using_snapuserd = using_snapuserd,
.compression_algorithm = compression_algorithm,
};
+ if (dap_metadata.vabc_feature_set().has_threaded()) {
+ cow_creator.enable_threading = dap_metadata.vabc_feature_set().threaded();
+ }
+ if (dap_metadata.vabc_feature_set().has_batch_writes()) {
+ cow_creator.batched_writes = dap_metadata.vabc_feature_set().batch_writes();
+ }
+ // In case of error, automatically delete devices that are created along the way.
+ // Note that "lock" is destroyed after "created_devices", so it is safe to use |lock| for
+ // these devices.
+ AutoDeviceList created_devices;
+ std::map<std::string, SnapshotStatus> all_snapshot_status;
auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
&all_snapshot_status);
- if (!ret.is_ok()) return ret;
+ if (!ret.is_ok()) {
+ LOG(ERROR) << "CreateUpdateSnapshotsInternal failed: " << ret.string();
+ return ret;
+ }
auto exported_target_metadata = target_metadata->Export();
if (exported_target_metadata == nullptr) {
@@ -3258,7 +3287,7 @@
return Return::Error();
}
- ret = InitializeUpdateSnapshots(lock.get(), target_metadata.get(),
+ ret = InitializeUpdateSnapshots(lock.get(), dap_metadata.cow_version(), target_metadata.get(),
exported_target_metadata.get(), target_suffix,
all_snapshot_status);
if (!ret.is_ok()) return ret;
@@ -3467,7 +3496,10 @@
// Create the backing COW image if necessary.
if (snapshot_status.cow_file_size() > 0) {
auto ret = CreateCowImage(lock, name);
- if (!ret.is_ok()) return AddRequiredSpace(ret, *all_snapshot_status);
+ if (!ret.is_ok()) {
+ LOG(ERROR) << "CreateCowImage failed: " << ret.string();
+ return AddRequiredSpace(ret, *all_snapshot_status);
+ }
}
LOG(INFO) << "Successfully created snapshot for " << name;
@@ -3477,7 +3509,7 @@
}
Return SnapshotManager::InitializeUpdateSnapshots(
- LockedFile* lock, MetadataBuilder* target_metadata,
+ LockedFile* lock, uint32_t cow_version, MetadataBuilder* target_metadata,
const LpMetadata* exported_target_metadata, const std::string& target_suffix,
const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
CHECK(lock);
@@ -3525,8 +3557,8 @@
}
options.compression = it->second.compression_algorithm();
- CowWriter writer(options);
- if (!writer.Initialize(fd) || !writer.Finalize()) {
+ auto writer = CreateCowWriter(cow_version, options, std::move(fd));
+ if (!writer->Finalize()) {
LOG(ERROR) << "Could not initialize COW device for " << target_partition->name();
return Return::Error();
}
@@ -3576,12 +3608,12 @@
return true;
}
-std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter(
+std::unique_ptr<ICowWriter> SnapshotManager::OpenSnapshotWriter(
const android::fs_mgr::CreateLogicalPartitionParams& params,
- const std::optional<std::string>& source_device) {
+ std::optional<uint64_t> label) {
#if defined(LIBSNAPSHOT_NO_COW_WRITE)
(void)params;
- (void)source_device;
+ (void)label;
LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery";
return nullptr;
@@ -3615,25 +3647,26 @@
return nullptr;
}
- if (status.using_snapuserd()) {
- return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(),
- status, paths);
+ if (!status.using_snapuserd()) {
+ LOG(ERROR) << "Can only create snapshot writers with userspace or compressed snapshots";
+ return nullptr;
}
- return OpenKernelSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status,
- paths);
+
+ return OpenCompressedSnapshotWriter(lock.get(), status, paths, label);
#endif
}
#if !defined(LIBSNAPSHOT_NO_COW_WRITE)
-std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter(
- LockedFile* lock, const std::optional<std::string>& source_device,
- [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status,
- const SnapshotPaths& paths) {
+std::unique_ptr<ICowWriter> SnapshotManager::OpenCompressedSnapshotWriter(
+ LockedFile* lock, const SnapshotStatus& status, const SnapshotPaths& paths,
+ std::optional<uint64_t> label) {
CHECK(lock);
CowOptions cow_options;
cow_options.compression = status.compression_algorithm();
cow_options.max_blocks = {status.device_size() / cow_options.block_size};
+ cow_options.batch_write = status.batched_writes();
+ cow_options.num_compress_threads = status.enable_threading() ? 2 : 0;
// Disable scratch space for vts tests
if (device()->IsTestDevice()) {
cow_options.scratch_space = false;
@@ -3643,11 +3676,6 @@
// never creates this scenario.
CHECK(status.snapshot_size() == status.device_size());
- auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options);
- if (source_device) {
- writer->SetSourceDevice(*source_device);
- }
-
std::string cow_path;
if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) {
LOG(ERROR) << "Could not determine path for " << paths.cow_device_name;
@@ -3659,40 +3687,14 @@
PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << cow_path;
return nullptr;
}
- if (!writer->SetCowDevice(std::move(cow_fd))) {
- LOG(ERROR) << "Could not create COW writer from " << cow_path;
+
+ CowHeader header;
+ if (!ReadCowHeader(cow_fd, &header)) {
+ LOG(ERROR) << "OpenCompressedSnapshotWriter: read header failed";
return nullptr;
}
- return writer;
-}
-
-std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter(
- LockedFile* lock, const std::optional<std::string>& source_device,
- [[maybe_unused]] const std::string& partition_name, const SnapshotStatus& status,
- const SnapshotPaths& paths) {
- CHECK(lock);
-
- CowOptions cow_options;
- cow_options.max_blocks = {status.device_size() / cow_options.block_size};
-
- auto writer = std::make_unique<OnlineKernelSnapshotWriter>(cow_options);
-
- std::string path = paths.snapshot_device.empty() ? paths.target_device : paths.snapshot_device;
- unique_fd fd(open(path.c_str(), O_RDWR | O_CLOEXEC));
- if (fd < 0) {
- PLOG(ERROR) << "open failed: " << path;
- return nullptr;
- }
-
- if (source_device) {
- writer->SetSourceDevice(*source_device);
- }
-
- uint64_t cow_size = status.cow_partition_size() + status.cow_file_size();
- writer->SetSnapshotDevice(std::move(fd), cow_size);
-
- return writer;
+ return CreateCowWriter(header.prefix.major_version, cow_options, std::move(cow_fd), label);
}
#endif // !defined(LIBSNAPSHOT_NO_COW_WRITE)
@@ -3744,7 +3746,7 @@
auto update_status = ReadSnapshotUpdateStatus(file.get());
- ss << "Update state: " << ReadUpdateState(file.get()) << std::endl;
+ ss << "Update state: " << update_status.state() << std::endl;
ss << "Using snapuserd: " << update_status.using_snapuserd() << std::endl;
ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
@@ -3759,6 +3761,17 @@
<< std::endl;
ss << "Source build fingerprint: " << update_status.source_build_fingerprint() << std::endl;
+ if (update_status.state() == UpdateState::Merging) {
+ ss << "Merge completion: ";
+ if (!EnsureSnapuserdConnected()) {
+ ss << "N/A";
+ } else {
+ ss << snapuserd_client_->GetMergePercent() << "%";
+ }
+ ss << std::endl;
+ ss << "Merge phase: " << update_status.merge_phase() << std::endl;
+ }
+
bool ok = true;
std::vector<std::string> snapshots;
if (!ListSnapshots(file.get(), &snapshots)) {
@@ -3781,6 +3794,7 @@
ss << " allocated sectors: " << status.sectors_allocated() << std::endl;
ss << " metadata sectors: " << status.metadata_sectors() << std::endl;
ss << " compression: " << status.compression_algorithm() << std::endl;
+ ss << " merge phase: " << DecideMergePhase(status) << std::endl;
}
os << ss.rdbuf();
return ok;
@@ -4349,5 +4363,16 @@
return status.source_build_fingerprint();
}
+bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() {
+ auto slot = GetCurrentSlot();
+ if (slot == Slot::Target) {
+ if (IsSnapuserdRequired()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz.cpp b/fs_mgr/libsnapshot/snapshot_fuzz.cpp
deleted file mode 100644
index aced3ed..0000000
--- a/fs_mgr/libsnapshot/snapshot_fuzz.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (C) 2020 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 <stddef.h>
-#include <stdint.h>
-#include <sysexits.h>
-
-#include <functional>
-#include <sstream>
-#include <tuple>
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/result.h>
-#include <gtest/gtest.h>
-#include <src/libfuzzer/libfuzzer_macro.h>
-#include <storage_literals/storage_literals.h>
-
-#include "fuzz_utils.h"
-#include "snapshot_fuzz_utils.h"
-
-using android::base::Error;
-using android::base::GetBoolProperty;
-using android::base::LogId;
-using android::base::LogSeverity;
-using android::base::ReadFileToString;
-using android::base::Result;
-using android::base::SetLogger;
-using android::base::StderrLogger;
-using android::base::StdioLogger;
-using android::fs_mgr::CreateLogicalPartitionParams;
-using android::fuzz::CheckedCast;
-using android::snapshot::SnapshotFuzzData;
-using android::snapshot::SnapshotFuzzEnv;
-using chromeos_update_engine::DeltaArchiveManifest;
-using google::protobuf::FieldDescriptor;
-using google::protobuf::Message;
-using google::protobuf::RepeatedPtrField;
-
-// Avoid linking to libgsi since it needs disk I/O.
-namespace android::gsi {
-bool IsGsiRunning() {
- LOG(FATAL) << "Called IsGsiRunning";
- __builtin_unreachable();
-}
-std::string GetDsuSlot(const std::string& install_dir) {
- LOG(FATAL) << "Called GetDsuSlot(" << install_dir << ")";
- __builtin_unreachable();
-}
-} // namespace android::gsi
-
-namespace android::snapshot {
-
-const SnapshotFuzzData* current_data = nullptr;
-const SnapshotTestModule* current_module = nullptr;
-
-SnapshotFuzzEnv* GetSnapshotFuzzEnv();
-
-FUZZ_CLASS(ISnapshotManager, SnapshotManagerAction);
-
-using ProcessUpdateStateArgs = SnapshotManagerAction::Proto::ProcessUpdateStateArgs;
-using CreateLogicalAndSnapshotPartitionsArgs =
- SnapshotManagerAction::Proto::CreateLogicalAndSnapshotPartitionsArgs;
-using RecoveryCreateSnapshotDevicesArgs =
- SnapshotManagerAction::Proto::RecoveryCreateSnapshotDevicesArgs;
-
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, BeginUpdate);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, CancelUpdate);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, InitiateMerge);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, NeedSnapshotsInFirstStageMount);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, RecoveryCreateSnapshotDevices);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, EnsureMetadataMounted);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, GetSnapshotMergeStatsInstance);
-
-#define SNAPSHOT_FUZZ_FUNCTION(FunctionName, ReturnType, ...) \
- FUZZ_FUNCTION(SnapshotManagerAction, FunctionName, ReturnType, ISnapshotManager* snapshot, \
- ##__VA_ARGS__)
-
-SNAPSHOT_FUZZ_FUNCTION(FinishedSnapshotWrites, bool, bool wipe) {
- return snapshot->FinishedSnapshotWrites(wipe);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(ProcessUpdateState, bool, const ProcessUpdateStateArgs& args) {
- std::function<bool()> before_cancel;
- if (args.has_before_cancel()) {
- before_cancel = [&]() { return args.fail_before_cancel(); };
- }
- return snapshot->ProcessUpdateState({}, before_cancel);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(GetUpdateState, UpdateState, bool has_progress_arg) {
- double progress;
- return snapshot->GetUpdateState(has_progress_arg ? &progress : nullptr);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(HandleImminentDataWipe, bool, bool has_callback) {
- std::function<void()> callback;
- if (has_callback) {
- callback = []() {};
- }
- return snapshot->HandleImminentDataWipe(callback);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(Dump, bool) {
- std::stringstream ss;
- return snapshot->Dump(ss);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(CreateUpdateSnapshots, bool, const DeltaArchiveManifest& manifest) {
- return snapshot->CreateUpdateSnapshots(manifest);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(UnmapUpdateSnapshot, bool, const std::string& name) {
- return snapshot->UnmapUpdateSnapshot(name);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(CreateLogicalAndSnapshotPartitions, bool,
- const CreateLogicalAndSnapshotPartitionsArgs& args) {
- const std::string* super;
- if (args.use_correct_super()) {
- super = &GetSnapshotFuzzEnv()->super();
- } else {
- super = &args.super();
- }
- return snapshot->CreateLogicalAndSnapshotPartitions(
- *super, std::chrono::milliseconds(args.timeout_millis()));
-}
-
-SNAPSHOT_FUZZ_FUNCTION(RecoveryCreateSnapshotDevicesWithMetadata, CreateResult,
- const RecoveryCreateSnapshotDevicesArgs& args) {
- std::unique_ptr<AutoDevice> device;
- if (args.has_metadata_device_object()) {
- device = std::make_unique<NoOpAutoDevice>(args.metadata_mounted());
- }
- return snapshot->RecoveryCreateSnapshotDevices(device);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(MapUpdateSnapshot, bool,
- const CreateLogicalPartitionParamsProto& params_proto) {
- auto partition_opener = std::make_unique<TestPartitionOpener>(GetSnapshotFuzzEnv()->super());
- CreateLogicalPartitionParams params;
- if (params_proto.use_correct_super()) {
- params.block_device = GetSnapshotFuzzEnv()->super();
- } else {
- params.block_device = params_proto.block_device();
- }
- if (params_proto.has_metadata_slot()) {
- params.metadata_slot = params_proto.metadata_slot();
- }
- params.partition_name = params_proto.partition_name();
- params.force_writable = params_proto.force_writable();
- params.timeout_ms = std::chrono::milliseconds(params_proto.timeout_millis());
- params.device_name = params_proto.device_name();
- params.partition_opener = partition_opener.get();
- std::string path;
- return snapshot->MapUpdateSnapshot(params, &path);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(SwitchSlot, void) {
- (void)snapshot;
- CHECK(current_module != nullptr);
- CHECK(current_module->device_info != nullptr);
- current_module->device_info->SwitchSlot();
-}
-
-// During global init, log all messages to stdio. This is only done once.
-int AllowLoggingDuringGlobalInit() {
- SetLogger(&StdioLogger);
- return 0;
-}
-
-// Only log fatal messages during tests.
-void FatalOnlyLogger(LogId logid, LogSeverity severity, const char* tag, const char* file,
- unsigned int line, const char* message) {
- if (severity == LogSeverity::FATAL) {
- StderrLogger(logid, severity, tag, file, line, message);
-
- // If test fails by a LOG(FATAL) or CHECK(), log the corpus. If it abort()'s, there's
- // nothing else we can do.
- StderrLogger(logid, severity, tag, __FILE__, __LINE__,
- "Attempting to dump current corpus:");
- if (current_data == nullptr) {
- StderrLogger(logid, severity, tag, __FILE__, __LINE__, "Current corpus is nullptr.");
- } else {
- std::string content;
- if (!google::protobuf::TextFormat::PrintToString(*current_data, &content)) {
- StderrLogger(logid, severity, tag, __FILE__, __LINE__,
- "Failed to print corpus to string.");
- } else {
- StderrLogger(logid, severity, tag, __FILE__, __LINE__, content.c_str());
- }
- }
- }
-}
-// Stop logging (except fatal messages) after global initialization. This is only done once.
-int StopLoggingAfterGlobalInit() {
- (void)GetSnapshotFuzzEnv();
- [[maybe_unused]] static protobuf_mutator::protobuf::LogSilencer log_silencer;
- SetLogger(&FatalOnlyLogger);
- return 0;
-}
-
-SnapshotFuzzEnv* GetSnapshotFuzzEnv() {
- [[maybe_unused]] static auto allow_logging = AllowLoggingDuringGlobalInit();
- static SnapshotFuzzEnv env;
- return &env;
-}
-
-SnapshotTestModule SetUpTest(const SnapshotFuzzData& snapshot_fuzz_data) {
- current_data = &snapshot_fuzz_data;
-
- auto env = GetSnapshotFuzzEnv();
- env->CheckSoftReset();
-
- auto test_module = env->CheckCreateSnapshotManager(snapshot_fuzz_data);
- current_module = &test_module;
- CHECK(test_module.snapshot);
- return test_module;
-}
-
-void TearDownTest() {
- current_module = nullptr;
- current_data = nullptr;
-}
-
-} // namespace android::snapshot
-
-DEFINE_PROTO_FUZZER(const SnapshotFuzzData& snapshot_fuzz_data) {
- using namespace android::snapshot;
-
- [[maybe_unused]] static auto stop_logging = StopLoggingAfterGlobalInit();
- auto test_module = SetUpTest(snapshot_fuzz_data);
- SnapshotManagerAction::ExecuteAll(test_module.snapshot.get(), snapshot_fuzz_data.actions());
- TearDownTest();
-}
-
-namespace android::snapshot {
-
-// Work-around to cast a 'void' value to Result<void>.
-template <typename T>
-struct GoodResult {
- template <typename F>
- static Result<T> Cast(F&& f) {
- return f();
- }
-};
-
-template <>
-struct GoodResult<void> {
- template <typename F>
- static Result<void> Cast(F&& f) {
- f();
- return {};
- }
-};
-
-class LibsnapshotFuzzerTest : public ::testing::Test {
- protected:
- static void SetUpTestCase() {
- // Do initialization once.
- (void)GetSnapshotFuzzEnv();
- }
- void SetUp() override {
- bool is_virtual_ab = GetBoolProperty("ro.virtual_ab.enabled", false);
- if (!is_virtual_ab) GTEST_SKIP() << "Test only runs on Virtual A/B devices.";
- }
- void SetUpFuzzData(const std::string& fn) {
- auto path = android::base::GetExecutableDirectory() + "/corpus/"s + fn;
- std::string proto_text;
- ASSERT_TRUE(ReadFileToString(path, &proto_text));
- snapshot_fuzz_data_ = std::make_unique<SnapshotFuzzData>();
- ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(proto_text,
- snapshot_fuzz_data_.get()));
- test_module_ = android::snapshot::SetUpTest(*snapshot_fuzz_data_);
- }
- void TearDown() override { android::snapshot::TearDownTest(); }
- template <typename FuzzFunction>
- Result<typename FuzzFunction::ReturnType> Execute(int action_index) {
- if (action_index >= snapshot_fuzz_data_->actions_size()) {
- return Error() << "Index " << action_index << " is out of bounds ("
- << snapshot_fuzz_data_->actions_size() << " actions in corpus";
- }
- const auto& action_proto = snapshot_fuzz_data_->actions(action_index);
- const auto* field_desc =
- android::fuzz::GetValueFieldDescriptor<typename FuzzFunction::ActionType>(
- action_proto);
- if (field_desc == nullptr) {
- return Error() << "Action at index " << action_index << " has no value defined.";
- }
- if (FuzzFunction::tag != field_desc->number()) {
- return Error() << "Action at index " << action_index << " is expected to be "
- << FuzzFunction::name << ", but it is " << field_desc->name()
- << " in corpus.";
- }
- return GoodResult<typename FuzzFunction::ReturnType>::Cast([&]() {
- return android::fuzz::ActionPerformer<FuzzFunction>::Invoke(test_module_.snapshot.get(),
- action_proto, field_desc);
- });
- }
-
- std::unique_ptr<SnapshotFuzzData> snapshot_fuzz_data_;
- SnapshotTestModule test_module_;
-};
-
-#define SNAPSHOT_FUZZ_FN_NAME(name) FUZZ_FUNCTION_CLASS_NAME(SnapshotManagerAction, name)
-
-MATCHER_P(ResultIs, expected, "") {
- if (!arg.ok()) {
- *result_listener << arg.error();
- return false;
- }
- *result_listener << "expected: " << expected;
- return arg.value() == expected;
-}
-
-#define ASSERT_RESULT_TRUE(actual) ASSERT_THAT(actual, ResultIs(true))
-
-// Check that launch_device.txt is executed correctly.
-TEST_F(LibsnapshotFuzzerTest, LaunchDevice) {
- SetUpFuzzData("launch_device.txt");
-
- int i = 0;
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(BeginUpdate)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(CreateUpdateSnapshots)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(MapUpdateSnapshot)>(i++)) << "sys_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(MapUpdateSnapshot)>(i++)) << "vnd_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(MapUpdateSnapshot)>(i++)) << "prd_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(FinishedSnapshotWrites)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(UnmapUpdateSnapshot)>(i++)) << "sys_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(UnmapUpdateSnapshot)>(i++)) << "vnd_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(UnmapUpdateSnapshot)>(i++)) << "prd_b";
- ASSERT_RESULT_OK(Execute<SNAPSHOT_FUZZ_FN_NAME(SwitchSlot)>(i++));
- ASSERT_EQ("_b", test_module_.device_info->GetSlotSuffix());
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(NeedSnapshotsInFirstStageMount)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(CreateLogicalAndSnapshotPartitions)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(InitiateMerge)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(ProcessUpdateState)>(i++));
- ASSERT_EQ(i, snapshot_fuzz_data_->actions_size()) << "Not all actions are executed.";
-}
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp b/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
deleted file mode 100644
index 54c6a00..0000000
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
-// Copyright (C) 2020 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 <ftw.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sysexits.h>
-
-#include <chrono>
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <fs_mgr.h>
-#include <libsnapshot/auto_device.h>
-#include <libsnapshot/snapshot.h>
-#include <storage_literals/storage_literals.h>
-
-#include "snapshot_fuzz_utils.h"
-#include "utility.h"
-
-// Prepends the errno string, but it is good enough.
-#ifndef PCHECK
-#define PCHECK(x) CHECK(x) << strerror(errno) << ": "
-#endif
-
-using namespace android::storage_literals;
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-
-using android::base::Basename;
-using android::base::ReadFileToString;
-using android::base::SetProperty;
-using android::base::Split;
-using android::base::StartsWith;
-using android::base::StringPrintf;
-using android::base::unique_fd;
-using android::base::WriteStringToFile;
-using android::dm::DeviceMapper;
-using android::dm::DmTarget;
-using android::dm::LoopControl;
-using android::fiemap::IImageManager;
-using android::fiemap::ImageManager;
-using android::fs_mgr::BlockDeviceInfo;
-using android::fs_mgr::FstabEntry;
-using android::fs_mgr::IPartitionOpener;
-using chromeos_update_engine::DynamicPartitionMetadata;
-
-static const char MNT_DIR[] = "/mnt";
-static const char BLOCK_SYSFS[] = "/sys/block";
-
-static const char FAKE_ROOT_NAME[] = "snapshot_fuzz";
-static const auto SUPER_IMAGE_SIZE = 16_MiB;
-static const auto DATA_IMAGE_SIZE = 16_MiB;
-static const auto FAKE_ROOT_SIZE = 64_MiB;
-
-namespace android::snapshot {
-
-bool Mkdir(const std::string& path) {
- if (mkdir(path.c_str(), 0750) == -1 && errno != EEXIST) {
- PLOG(ERROR) << "Cannot create " << path;
- return false;
- }
- return true;
-}
-
-bool RmdirRecursive(const std::string& path) {
- auto callback = [](const char* child, const struct stat*, int file_type, struct FTW*) -> int {
- switch (file_type) {
- case FTW_D:
- case FTW_DP:
- case FTW_DNR:
- if (rmdir(child) == -1) {
- PLOG(ERROR) << "rmdir " << child;
- return -1;
- }
- return 0;
- case FTW_NS:
- default:
- if (rmdir(child) != -1) break;
- [[fallthrough]];
- case FTW_F:
- case FTW_SL:
- case FTW_SLN:
- if (unlink(child) == -1) {
- PLOG(ERROR) << "unlink " << child;
- return -1;
- }
- return 0;
- }
- return 0;
- };
-
- return nftw(path.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0;
-}
-
-std::string GetLinearBaseDeviceString(const DeviceMapper::TargetInfo& target) {
- if (target.spec.target_type != "linear"s) return {};
- auto tokens = Split(target.data, " ");
- CHECK_EQ(2, tokens.size());
- return tokens[0];
-}
-
-std::vector<std::string> GetSnapshotBaseDeviceStrings(const DeviceMapper::TargetInfo& target) {
- if (target.spec.target_type != "snapshot"s && target.spec.target_type != "snapshot-merge"s)
- return {};
- auto tokens = Split(target.data, " ");
- CHECK_EQ(4, tokens.size());
- return {tokens[0], tokens[1]};
-}
-
-bool ShouldDeleteLoopDevice(const std::string& node) {
- std::string backing_file;
- if (ReadFileToString(StringPrintf("%s/loop/backing_file", node.data()), &backing_file)) {
- if (StartsWith(backing_file, std::string(MNT_DIR) + "/" + FAKE_ROOT_NAME)) {
- return true;
- }
- }
- return false;
-}
-
-std::vector<DeviceMapper::TargetInfo> GetTableInfoIfExists(const std::string& dev_name) {
- auto& dm = DeviceMapper::Instance();
- std::vector<DeviceMapper::TargetInfo> table;
- if (!dm.GetTableInfo(dev_name, &table)) {
- PCHECK(errno == ENODEV || errno == ENXIO);
- return {};
- }
- return table;
-}
-
-std::set<std::string> GetAllBaseDeviceStrings(const std::string& child_dev) {
- std::set<std::string> ret;
- for (const auto& child_target : GetTableInfoIfExists(child_dev)) {
- auto snapshot_bases = GetSnapshotBaseDeviceStrings(child_target);
- ret.insert(snapshot_bases.begin(), snapshot_bases.end());
-
- auto linear_base = GetLinearBaseDeviceString(child_target);
- if (!linear_base.empty()) {
- ret.insert(linear_base);
- }
- }
- return ret;
-}
-
-using PropertyList = std::set<std::string>;
-void InsertProperty(const char* key, const char* /*name*/, void* cookie) {
- reinterpret_cast<PropertyList*>(cookie)->insert(key);
-}
-
-// Attempt to delete all devices that is based on dev_name, including itself.
-void CheckDeleteDeviceMapperTree(const std::string& dev_name, bool known_allow_delete = false,
- uint64_t depth = 100) {
- CHECK(depth > 0) << "Reaching max depth when deleting " << dev_name
- << ". There may be devices referencing itself. Check `dmctl list devices -v`.";
-
- auto& dm = DeviceMapper::Instance();
- auto table = GetTableInfoIfExists(dev_name);
- if (table.empty()) {
- PCHECK(dm.DeleteDeviceIfExists(dev_name)) << dev_name;
- return;
- }
-
- if (!known_allow_delete) {
- for (const auto& target : table) {
- auto base_device_string = GetLinearBaseDeviceString(target);
- if (base_device_string.empty()) continue;
- if (ShouldDeleteLoopDevice(
- StringPrintf("/sys/dev/block/%s", base_device_string.data()))) {
- known_allow_delete = true;
- break;
- }
- }
- }
- if (!known_allow_delete) {
- return;
- }
-
- std::string dev_string;
- PCHECK(dm.GetDeviceString(dev_name, &dev_string));
-
- std::vector<DeviceMapper::DmBlockDevice> devices;
- PCHECK(dm.GetAvailableDevices(&devices));
- for (const auto& child_dev : devices) {
- auto child_bases = GetAllBaseDeviceStrings(child_dev.name());
- if (child_bases.find(dev_string) != child_bases.end()) {
- CheckDeleteDeviceMapperTree(child_dev.name(), true /* known_allow_delete */, depth - 1);
- }
- }
-
- PCHECK(dm.DeleteDeviceIfExists(dev_name)) << dev_name;
-}
-
-// Attempt to clean up residues from previous runs.
-void CheckCleanupDeviceMapperDevices() {
- auto& dm = DeviceMapper::Instance();
- std::vector<DeviceMapper::DmBlockDevice> devices;
- PCHECK(dm.GetAvailableDevices(&devices));
-
- for (const auto& dev : devices) {
- CheckDeleteDeviceMapperTree(dev.name());
- }
-}
-
-void CheckUmount(const std::string& path) {
- PCHECK(TEMP_FAILURE_RETRY(umount(path.data()) == 0) || errno == ENOENT || errno == EINVAL)
- << path;
-}
-
-void CheckDetachLoopDevices(const std::set<std::string>& exclude_names = {}) {
- // ~SnapshotFuzzEnv automatically does the following.
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(BLOCK_SYSFS), closedir);
- PCHECK(dir != nullptr) << BLOCK_SYSFS;
- LoopControl loop_control;
- dirent* dp;
- while ((dp = readdir(dir.get())) != nullptr) {
- if (exclude_names.find(dp->d_name) != exclude_names.end()) {
- continue;
- }
- if (!ShouldDeleteLoopDevice(StringPrintf("%s/%s", BLOCK_SYSFS, dp->d_name).data())) {
- continue;
- }
- PCHECK(loop_control.Detach(StringPrintf("/dev/block/%s", dp->d_name).data()));
- }
-}
-
-void CheckUmountAll() {
- CheckUmount(std::string(MNT_DIR) + "/snapshot_fuzz_data");
- CheckUmount(std::string(MNT_DIR) + "/" + FAKE_ROOT_NAME);
-}
-
-class AutoDeleteDir : public AutoDevice {
- public:
- static std::unique_ptr<AutoDeleteDir> New(const std::string& path) {
- if (!Mkdir(path)) {
- return std::unique_ptr<AutoDeleteDir>(new AutoDeleteDir(""));
- }
- return std::unique_ptr<AutoDeleteDir>(new AutoDeleteDir(path));
- }
- ~AutoDeleteDir() {
- if (!HasDevice()) return;
- PCHECK(rmdir(name_.c_str()) == 0 || errno == ENOENT) << name_;
- }
-
- private:
- AutoDeleteDir(const std::string& path) : AutoDevice(path) {}
-};
-
-class AutoUnmount : public AutoDevice {
- public:
- ~AutoUnmount() {
- if (!HasDevice()) return;
- CheckUmount(name_);
- }
- AutoUnmount(const std::string& path) : AutoDevice(path) {}
-};
-
-class AutoUnmountTmpfs : public AutoUnmount {
- public:
- static std::unique_ptr<AutoUnmount> New(const std::string& path, uint64_t size) {
- if (mount("tmpfs", path.c_str(), "tmpfs", 0,
- (void*)StringPrintf("size=%" PRIu64, size).data()) == -1) {
- PLOG(ERROR) << "Cannot mount " << path;
- return std::unique_ptr<AutoUnmount>(new AutoUnmount(""));
- }
- return std::unique_ptr<AutoUnmount>(new AutoUnmount(path));
- }
- private:
- using AutoUnmount::AutoUnmount;
-};
-
-// A directory on tmpfs. Upon destruct, it is unmounted and deleted.
-class AutoMemBasedDir : public AutoDevice {
- public:
- static std::unique_ptr<AutoMemBasedDir> New(const std::string& name, uint64_t size) {
- auto ret = std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(name));
- ret->auto_delete_mount_dir_ = AutoDeleteDir::New(ret->mount_path());
- if (!ret->auto_delete_mount_dir_->HasDevice()) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- ret->auto_umount_mount_point_ = AutoUnmountTmpfs::New(ret->mount_path(), size);
- if (!ret->auto_umount_mount_point_->HasDevice()) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- // tmp_path() and persist_path does not need to be deleted upon destruction, hence it is
- // not wrapped with AutoDeleteDir.
- if (!Mkdir(ret->tmp_path())) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- if (!Mkdir(ret->persist_path())) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- return ret;
- }
- // Return the temporary scratch directory.
- std::string tmp_path() const {
- CHECK(HasDevice());
- return mount_path() + "/tmp";
- }
- // Return the temporary scratch directory.
- std::string persist_path() const {
- CHECK(HasDevice());
- return mount_path() + "/persist";
- }
- // Delete all contents in tmp_path() and start over. tmp_path() itself is re-created.
- void CheckSoftReset() {
- PCHECK(RmdirRecursive(tmp_path()));
- PCHECK(Mkdir(tmp_path()));
- }
-
- private:
- AutoMemBasedDir(const std::string& name) : AutoDevice(name) {}
- std::string mount_path() const {
- CHECK(HasDevice());
- return MNT_DIR + "/"s + name_;
- }
- std::unique_ptr<AutoDeleteDir> auto_delete_mount_dir_;
- std::unique_ptr<AutoUnmount> auto_umount_mount_point_;
-};
-
-SnapshotFuzzEnv::SnapshotFuzzEnv() {
- CheckCleanupDeviceMapperDevices();
- CheckDetachLoopDevices();
- CheckUmountAll();
-
- fake_root_ = AutoMemBasedDir::New(FAKE_ROOT_NAME, FAKE_ROOT_SIZE);
- CHECK(fake_root_ != nullptr);
- CHECK(fake_root_->HasDevice());
- loop_control_ = std::make_unique<LoopControl>();
-
- fake_data_mount_point_ = MNT_DIR + "/snapshot_fuzz_data"s;
- auto_delete_data_mount_point_ = AutoDeleteDir::New(fake_data_mount_point_);
- CHECK(auto_delete_data_mount_point_ != nullptr);
- CHECK(auto_delete_data_mount_point_->HasDevice());
-
- const auto& fake_persist_path = fake_root_->persist_path();
- mapped_super_ = CheckMapImage(fake_persist_path + "/super.img", SUPER_IMAGE_SIZE,
- loop_control_.get(), &fake_super_);
- mapped_data_ = CheckMapImage(fake_persist_path + "/data.img", DATA_IMAGE_SIZE,
- loop_control_.get(), &fake_data_block_device_);
- mounted_data_ = CheckMountFormatData(fake_data_block_device_, fake_data_mount_point_);
-}
-
-SnapshotFuzzEnv::~SnapshotFuzzEnv() {
- CheckCleanupDeviceMapperDevices();
- mounted_data_ = nullptr;
- auto_delete_data_mount_point_ = nullptr;
- mapped_data_ = nullptr;
- mapped_super_ = nullptr;
- CheckDetachLoopDevices();
- loop_control_ = nullptr;
- fake_root_ = nullptr;
- CheckUmountAll();
-}
-
-void CheckZeroFill(const std::string& file, size_t size) {
- std::string zeros(size, '\0');
- PCHECK(WriteStringToFile(zeros, file)) << "Cannot write zeros to " << file;
-}
-
-void SnapshotFuzzEnv::CheckSoftReset() {
- fake_root_->CheckSoftReset();
- CheckZeroFill(super(), SUPER_IMAGE_SIZE);
- CheckCleanupDeviceMapperDevices();
- CheckDetachLoopDevices({Basename(fake_super_), Basename(fake_data_block_device_)});
-}
-
-std::unique_ptr<IImageManager> SnapshotFuzzEnv::CheckCreateFakeImageManager() {
- auto metadata_dir = fake_root_->tmp_path() + "/images_manager_metadata";
- auto data_dir = fake_data_mount_point_ + "/image_manager_data";
- PCHECK(Mkdir(metadata_dir));
- PCHECK(Mkdir(data_dir));
- return SnapshotFuzzImageManager::Open(metadata_dir, data_dir);
-}
-
-// Helper to create a loop device for a file.
-static void CheckCreateLoopDevice(LoopControl* control, const std::string& file,
- const std::chrono::milliseconds& timeout_ms, std::string* path) {
- static constexpr int kOpenFlags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
- android::base::unique_fd file_fd(open(file.c_str(), kOpenFlags));
- PCHECK(file_fd >= 0) << "Could not open file: " << file;
- CHECK(control->Attach(file_fd, timeout_ms, path))
- << "Could not create loop device for: " << file;
-}
-
-class AutoDetachLoopDevice : public AutoDevice {
- public:
- AutoDetachLoopDevice(LoopControl* control, const std::string& device)
- : AutoDevice(device), control_(control) {}
- ~AutoDetachLoopDevice() { PCHECK(control_->Detach(name_)) << name_; }
-
- private:
- LoopControl* control_;
-};
-
-std::unique_ptr<AutoDevice> SnapshotFuzzEnv::CheckMapImage(const std::string& img_path,
- uint64_t size, LoopControl* control,
- std::string* mapped_path) {
- CheckZeroFill(img_path, size);
- CheckCreateLoopDevice(control, img_path, 1s, mapped_path);
-
- return std::make_unique<AutoDetachLoopDevice>(control, *mapped_path);
-}
-
-SnapshotTestModule SnapshotFuzzEnv::CheckCreateSnapshotManager(const SnapshotFuzzData& data) {
- SnapshotTestModule ret;
- auto partition_opener = std::make_unique<TestPartitionOpener>(super());
- ret.opener = partition_opener.get();
- CheckWriteSuperMetadata(data, *partition_opener);
- auto metadata_dir = fake_root_->tmp_path() + "/snapshot_metadata";
- PCHECK(Mkdir(metadata_dir));
- if (data.has_metadata_snapshots_dir()) {
- PCHECK(Mkdir(metadata_dir + "/snapshots"));
- }
-
- ret.device_info = new SnapshotFuzzDeviceInfo(this, data.device_info_data(),
- std::move(partition_opener), metadata_dir);
- auto snapshot = SnapshotManager::New(ret.device_info /* takes ownership */);
- ret.snapshot = std::move(snapshot);
-
- return ret;
-}
-
-const std::string& SnapshotFuzzEnv::super() const {
- return fake_super_;
-}
-
-void SnapshotFuzzEnv::CheckWriteSuperMetadata(const SnapshotFuzzData& data,
- const IPartitionOpener& opener) {
- if (!data.is_super_metadata_valid()) {
- // Leave it zero.
- return;
- }
-
- BlockDeviceInfo super_device("super", SUPER_IMAGE_SIZE, 0, 0, 4096);
- std::vector<BlockDeviceInfo> devices = {super_device};
- auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
- CHECK(builder != nullptr);
-
- // Attempt to create a super partition metadata using proto. All errors are ignored.
- for (const auto& group_proto : data.super_data().dynamic_partition_metadata().groups()) {
- (void)builder->AddGroup(group_proto.name(), group_proto.size());
- for (const auto& partition_name : group_proto.partition_names()) {
- (void)builder->AddPartition(partition_name, group_proto.name(),
- LP_PARTITION_ATTR_READONLY);
- }
- }
-
- for (const auto& partition_proto : data.super_data().partitions()) {
- auto p = builder->FindPartition(partition_proto.partition_name());
- if (p == nullptr) continue;
- (void)builder->ResizePartition(p, partition_proto.new_partition_info().size());
- }
-
- auto metadata = builder->Export();
- // metadata may be nullptr if it is not valid (e.g. partition name too long).
- // In this case, just use empty super partition data.
- if (metadata == nullptr) {
- builder = MetadataBuilder::New(devices, "super", 65536, 2);
- CHECK(builder != nullptr);
- metadata = builder->Export();
- CHECK(metadata != nullptr);
- }
- CHECK(FlashPartitionTable(opener, super(), *metadata.get()));
-}
-
-std::unique_ptr<AutoDevice> SnapshotFuzzEnv::CheckMountFormatData(const std::string& blk_device,
- const std::string& mount_point) {
- FstabEntry entry{
- .blk_device = blk_device,
- .length = static_cast<off64_t>(DATA_IMAGE_SIZE),
- .fs_type = "ext4",
- .mount_point = mount_point,
- };
- CHECK(0 == fs_mgr_do_format(entry));
- CHECK(0 == fs_mgr_do_mount_one(entry));
- return std::make_unique<AutoUnmount>(mount_point);
-}
-
-SnapshotFuzzImageManager::~SnapshotFuzzImageManager() {
- // Remove relevant gsid.mapped_images.* props.
- for (const auto& name : mapped_) {
- CHECK(UnmapImageIfExists(name)) << "Cannot unmap " << name;
- }
-}
-
-bool SnapshotFuzzImageManager::MapImageDevice(const std::string& name,
- const std::chrono::milliseconds& timeout_ms,
- std::string* path) {
- if (impl_->MapImageDevice(name, timeout_ms, path)) {
- mapped_.insert(name);
- return true;
- }
- return false;
-}
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
deleted file mode 100644
index eb8246a..0000000
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (C) 2020 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 <memory>
-#include <set>
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android/snapshot/snapshot_fuzz.pb.h>
-#include <libdm/loop_control.h>
-#include <libfiemap/image_manager.h>
-#include <liblp/liblp.h>
-#include <libsnapshot/auto_device.h>
-#include <libsnapshot/test_helpers.h>
-
-// libsnapshot-specific code for fuzzing. Defines fake classes that are depended
-// by SnapshotManager.
-
-#include "android/snapshot/snapshot_fuzz.pb.h"
-#include "libsnapshot/snapshot.h"
-
-namespace android::snapshot {
-
-class AutoMemBasedDir;
-class SnapshotFuzzDeviceInfo;
-
-class NoOpAutoDevice : public AutoDevice {
- public:
- NoOpAutoDevice(bool mounted) : AutoDevice(mounted ? "no_op" : "") {}
-};
-
-struct SnapshotTestModule {
- std::unique_ptr<ISnapshotManager> snapshot;
- SnapshotFuzzDeviceInfo* device_info = nullptr;
- TestPartitionOpener* opener = nullptr;
-};
-
-// Prepare test environment. This has a heavy overhead and should be done once.
-class SnapshotFuzzEnv {
- public:
- // Check if test should run at all.
- static bool ShouldSkipTest();
-
- // Initialize the environment.
- SnapshotFuzzEnv();
- ~SnapshotFuzzEnv();
-
- // Soft reset part of the environment before running the next test.
- // Abort if fails.
- void CheckSoftReset();
-
- // Create a snapshot manager for this test run.
- // Client is responsible for maintaining the lifetime of |data| over the life time of
- // ISnapshotManager.
- SnapshotTestModule CheckCreateSnapshotManager(const SnapshotFuzzData& data);
-
- std::unique_ptr<android::fiemap::IImageManager> CheckCreateFakeImageManager();
-
- // Return path to super partition.
- const std::string& super() const;
-
- private:
- std::unique_ptr<AutoMemBasedDir> fake_root_;
- std::unique_ptr<android::dm::LoopControl> loop_control_;
- std::string fake_data_mount_point_;
- std::unique_ptr<AutoDevice> auto_delete_data_mount_point_;
- std::unique_ptr<AutoDevice> mapped_super_;
- std::string fake_super_;
- std::unique_ptr<AutoDevice> mapped_data_;
- std::string fake_data_block_device_;
- std::unique_ptr<AutoDevice> mounted_data_;
-
- static std::unique_ptr<AutoDevice> CheckMapImage(const std::string& fake_persist_path,
- uint64_t size,
- android::dm::LoopControl* control,
- std::string* mapped_path);
- static std::unique_ptr<AutoDevice> CheckMountFormatData(const std::string& blk_device,
- const std::string& mount_point);
-
- void CheckWriteSuperMetadata(const SnapshotFuzzData& proto,
- const android::fs_mgr::IPartitionOpener& opener);
-};
-
-class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
- public:
- using MergeStatus = ISnapshotManager::IDeviceInfo::MergeStatus;
- // Client is responsible for maintaining the lifetime of |data|.
- SnapshotFuzzDeviceInfo(SnapshotFuzzEnv* env, const FuzzDeviceInfoData& data,
- std::unique_ptr<TestPartitionOpener>&& partition_opener,
- const std::string& metadata_dir)
- : env_(env),
- data_(&data),
- partition_opener_(std::move(partition_opener)),
- metadata_dir_(metadata_dir),
- dm_(android::dm::DeviceMapper::Instance()) {}
-
- // Following APIs are mocked.
- std::string GetMetadataDir() const override { return metadata_dir_; }
- std::string GetSuperDevice(uint32_t) const override {
- // TestPartitionOpener can recognize this.
- return "super";
- }
- const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
- return *partition_opener_;
- }
-
- // Following APIs are fuzzed.
- std::string GetSlotSuffix() const override { return CurrentSlotIsA() ? "_a" : "_b"; }
- std::string GetOtherSlotSuffix() const override { return CurrentSlotIsA() ? "_b" : "_a"; }
- bool IsOverlayfsSetup() const override { return data_->is_overlayfs_setup(); }
- bool SetBootControlMergeStatus(MergeStatus) override {
- return data_->allow_set_boot_control_merge_status();
- }
- bool SetSlotAsUnbootable(unsigned int) override {
- return data_->allow_set_slot_as_unbootable();
- }
- bool IsRecovery() const override { return data_->is_recovery(); }
- bool IsFirstStageInit() const override { return false; }
- android::dm::IDeviceMapper& GetDeviceMapper() override { return dm_; }
- std::unique_ptr<IImageManager> OpenImageManager() const {
- return env_->CheckCreateFakeImageManager();
- }
-
- void SwitchSlot() { switched_slot_ = !switched_slot_; }
-
- private:
- SnapshotFuzzEnv* env_;
- const FuzzDeviceInfoData* data_;
- std::unique_ptr<TestPartitionOpener> partition_opener_;
- std::string metadata_dir_;
- bool switched_slot_ = false;
- android::dm::DeviceMapper& dm_;
-
- bool CurrentSlotIsA() const { return data_->slot_suffix_is_a() != switched_slot_; }
-};
-
-// A spy class on ImageManager implementation. Upon destruction, unmaps all images
-// map through this object.
-class SnapshotFuzzImageManager : public android::fiemap::IImageManager {
- public:
- static std::unique_ptr<SnapshotFuzzImageManager> Open(const std::string& metadata_dir,
- const std::string& data_dir) {
- auto impl = android::fiemap::ImageManager::Open(metadata_dir, data_dir);
- if (impl == nullptr) return nullptr;
- return std::unique_ptr<SnapshotFuzzImageManager>(
- new SnapshotFuzzImageManager(std::move(impl)));
- }
-
- ~SnapshotFuzzImageManager();
-
- // Spied APIs.
- bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
- std::string* path) override;
-
- // Other functions call through.
- android::fiemap::FiemapStatus CreateBackingImage(
- const std::string& name, uint64_t size, int flags,
- std::function<bool(uint64_t, uint64_t)>&& on_progress) override {
- return impl_->CreateBackingImage(name, size, flags, std::move(on_progress));
- }
- bool DeleteBackingImage(const std::string& name) override {
- return impl_->DeleteBackingImage(name);
- }
- bool UnmapImageDevice(const std::string& name) override {
- return impl_->UnmapImageDevice(name);
- }
- bool BackingImageExists(const std::string& name) override {
- return impl_->BackingImageExists(name);
- }
- bool IsImageMapped(const std::string& name) override { return impl_->IsImageMapped(name); }
- bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
- std::string* dev) override {
- return impl_->MapImageWithDeviceMapper(opener, name, dev);
- }
- bool GetMappedImageDevice(const std::string& name, std::string* device) override {
- return impl_->GetMappedImageDevice(name, device);
- }
- bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override {
- return impl_->MapAllImages(init);
- }
- bool DisableImage(const std::string& name) override { return impl_->DisableImage(name); }
- bool RemoveDisabledImages() override { return impl_->RemoveDisabledImages(); }
- std::vector<std::string> GetAllBackingImages() override { return impl_->GetAllBackingImages(); }
- android::fiemap::FiemapStatus ZeroFillNewImage(const std::string& name,
- uint64_t bytes) override {
- return impl_->ZeroFillNewImage(name, bytes);
- }
- bool RemoveAllImages() override { return impl_->RemoveAllImages(); }
- bool UnmapImageIfExists(const std::string& name) override {
- return impl_->UnmapImageIfExists(name);
- }
- bool IsImageDisabled(const std::string& name) override { return impl_->IsImageDisabled(name); }
-
- private:
- std::unique_ptr<android::fiemap::IImageManager> impl_;
- std::set<std::string> mapped_;
-
- SnapshotFuzzImageManager(std::unique_ptr<android::fiemap::IImageManager>&& impl)
- : impl_(std::move(impl)) {}
-};
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/snapshot_reader.cpp
deleted file mode 100644
index 6546c2a..0000000
--- a/fs_mgr/libsnapshot/snapshot_reader.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-//
-// Copyright (C) 2020 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 "snapshot_reader.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <ext4_utils/ext4_utils.h>
-
-namespace android {
-namespace snapshot {
-
-using android::base::borrowed_fd;
-
-// Not supported.
-bool ReadOnlyFileDescriptor::Open(const char*, int, mode_t) {
- errno = EINVAL;
- return false;
-}
-
-bool ReadOnlyFileDescriptor::Open(const char*, int) {
- errno = EINVAL;
- return false;
-}
-
-ssize_t ReadOnlyFileDescriptor::Write(const void*, size_t) {
- errno = EINVAL;
- return false;
-}
-
-bool ReadOnlyFileDescriptor::BlkIoctl(int, uint64_t, uint64_t, int*) {
- errno = EINVAL;
- return false;
-}
-
-ReadFdFileDescriptor::ReadFdFileDescriptor(android::base::unique_fd&& fd) : fd_(std::move(fd)) {}
-
-ssize_t ReadFdFileDescriptor::Read(void* buf, size_t count) {
- return read(fd_.get(), buf, count);
-}
-
-off64_t ReadFdFileDescriptor::Seek(off64_t offset, int whence) {
- return lseek(fd_.get(), offset, whence);
-}
-
-uint64_t ReadFdFileDescriptor::BlockDevSize() {
- return get_block_device_size(fd_.get());
-}
-
-bool ReadFdFileDescriptor::Close() {
- fd_ = {};
- return true;
-}
-
-bool ReadFdFileDescriptor::IsSettingErrno() {
- return true;
-}
-
-bool ReadFdFileDescriptor::IsOpen() {
- return fd_ >= 0;
-}
-
-bool ReadFdFileDescriptor::Flush() {
- return true;
-}
-
-bool CompressedSnapshotReader::SetCow(std::unique_ptr<CowReader>&& cow) {
- cow_ = std::move(cow);
-
- CowHeader header;
- if (!cow_->GetHeader(&header)) {
- return false;
- }
- block_size_ = header.block_size;
-
- // Populate the operation map.
- op_iter_ = cow_->GetOpIter();
- while (!op_iter_->Done()) {
- const CowOperation* op = &op_iter_->Get();
- if (IsMetadataOp(*op)) {
- op_iter_->Next();
- continue;
- }
- if (op->new_block >= ops_.size()) {
- ops_.resize(op->new_block + 1, nullptr);
- }
- ops_[op->new_block] = op;
- op_iter_->Next();
- }
-
- return true;
-}
-
-void CompressedSnapshotReader::SetSourceDevice(const std::string& source_device) {
- source_device_ = {source_device};
-}
-
-void CompressedSnapshotReader::SetBlockDeviceSize(uint64_t block_device_size) {
- block_device_size_ = block_device_size;
-}
-
-borrowed_fd CompressedSnapshotReader::GetSourceFd() {
- if (source_fd_ < 0) {
- if (!source_device_) {
- LOG(ERROR) << "CompressedSnapshotReader needs source device, but none was set";
- errno = EINVAL;
- return {-1};
- }
- source_fd_.reset(open(source_device_->c_str(), O_RDONLY | O_CLOEXEC));
- if (source_fd_ < 0) {
- PLOG(ERROR) << "open " << *source_device_;
- return {-1};
- }
- }
- return source_fd_;
-}
-
-class MemoryByteSink : public IByteSink {
- public:
- MemoryByteSink(void* buf, size_t count) {
- buf_ = reinterpret_cast<uint8_t*>(buf);
- pos_ = buf_;
- end_ = buf_ + count;
- }
-
- void* GetBuffer(size_t requested, size_t* actual) override {
- *actual = std::min(remaining(), requested);
- if (!*actual) {
- return nullptr;
- }
-
- uint8_t* start = pos_;
- pos_ += *actual;
- return start;
- }
-
- bool ReturnData(void*, size_t) override { return true; }
-
- uint8_t* buf() const { return buf_; }
- uint8_t* pos() const { return pos_; }
- size_t remaining() const { return end_ - pos_; }
-
- private:
- uint8_t* buf_;
- uint8_t* pos_;
- uint8_t* end_;
-};
-
-ssize_t CompressedSnapshotReader::Read(void* buf, size_t count) {
- // Find the start and end chunks, inclusive.
- uint64_t start_chunk = offset_ / block_size_;
- uint64_t end_chunk = (offset_ + count - 1) / block_size_;
-
- // Chop off the first N bytes if the position is not block-aligned.
- size_t start_offset = offset_ % block_size_;
-
- MemoryByteSink sink(buf, count);
-
- size_t initial_bytes = std::min(block_size_ - start_offset, sink.remaining());
- ssize_t rv = ReadBlock(start_chunk, &sink, start_offset, initial_bytes);
- if (rv < 0) {
- return -1;
- }
- offset_ += rv;
-
- for (uint64_t chunk = start_chunk + 1; chunk < end_chunk; chunk++) {
- ssize_t rv = ReadBlock(chunk, &sink, 0);
- if (rv < 0) {
- return -1;
- }
- offset_ += rv;
- }
-
- if (sink.remaining()) {
- ssize_t rv = ReadBlock(end_chunk, &sink, 0, {sink.remaining()});
- if (rv < 0) {
- return -1;
- }
- offset_ += rv;
- }
-
- errno = 0;
-
- DCHECK(sink.pos() - sink.buf() == count);
- return count;
-}
-
-// Discard the first N bytes of a sink request, or any excess bytes.
-class PartialSink : public MemoryByteSink {
- public:
- PartialSink(void* buffer, size_t size, size_t ignore_start)
- : MemoryByteSink(buffer, size), ignore_start_(ignore_start) {}
-
- void* GetBuffer(size_t requested, size_t* actual) override {
- // Throw away the first N bytes if needed.
- if (ignore_start_) {
- *actual = std::min({requested, ignore_start_, sizeof(discard_)});
- ignore_start_ -= *actual;
- return discard_;
- }
- // Throw away any excess bytes if needed.
- if (remaining() == 0) {
- *actual = std::min(requested, sizeof(discard_));
- return discard_;
- }
- return MemoryByteSink::GetBuffer(requested, actual);
- }
-
- private:
- size_t ignore_start_;
- char discard_[BLOCK_SZ];
-};
-
-ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, IByteSink* sink, size_t start_offset,
- const std::optional<uint64_t>& max_bytes) {
- size_t bytes_to_read = block_size_;
- if (max_bytes) {
- bytes_to_read = *max_bytes;
- }
-
- // The offset is relative to the chunk; we should be reading no more than
- // one chunk.
- CHECK(start_offset + bytes_to_read <= block_size_);
-
- const CowOperation* op = nullptr;
- if (chunk < ops_.size()) {
- op = ops_[chunk];
- }
-
- size_t actual;
- void* buffer = sink->GetBuffer(bytes_to_read, &actual);
- if (!buffer || actual < bytes_to_read) {
- // This should never happen unless we calculated the read size wrong
- // somewhere. MemoryByteSink always fulfills the entire requested
- // region unless there's not enough buffer remaining.
- LOG(ERROR) << "Asked for buffer of size " << bytes_to_read << ", got " << actual;
- errno = EINVAL;
- return -1;
- }
-
- if (!op || op->type == kCowCopyOp) {
- borrowed_fd fd = GetSourceFd();
- if (fd < 0) {
- // GetSourceFd sets errno.
- return -1;
- }
-
- if (op) {
- chunk = op->source;
- }
-
- off64_t offset = (chunk * block_size_) + start_offset;
- if (!android::base::ReadFullyAtOffset(fd, buffer, bytes_to_read, offset)) {
- PLOG(ERROR) << "read " << *source_device_;
- // ReadFullyAtOffset sets errno.
- return -1;
- }
- } else if (op->type == kCowZeroOp) {
- memset(buffer, 0, bytes_to_read);
- } else if (op->type == kCowReplaceOp) {
- PartialSink partial_sink(buffer, bytes_to_read, start_offset);
- if (!cow_->ReadData(*op, &partial_sink)) {
- LOG(ERROR) << "CompressedSnapshotReader failed to read replace op";
- errno = EIO;
- return -1;
- }
- } else if (op->type == kCowXorOp) {
- borrowed_fd fd = GetSourceFd();
- if (fd < 0) {
- // GetSourceFd sets errno.
- return -1;
- }
-
- off64_t offset = op->source + start_offset;
- char data[BLOCK_SZ];
- if (!android::base::ReadFullyAtOffset(fd, &data, bytes_to_read, offset)) {
- PLOG(ERROR) << "read " << *source_device_;
- // ReadFullyAtOffset sets errno.
- return -1;
- }
- PartialSink partial_sink(buffer, bytes_to_read, start_offset);
- if (!cow_->ReadData(*op, &partial_sink)) {
- LOG(ERROR) << "CompressedSnapshotReader failed to read xor op";
- errno = EIO;
- return -1;
- }
- for (size_t i = 0; i < bytes_to_read; i++) {
- ((char*)buffer)[i] ^= data[i];
- }
- } else {
- LOG(ERROR) << "CompressedSnapshotReader unknown op type: " << uint32_t(op->type);
- errno = EINVAL;
- return -1;
- }
-
- // MemoryByteSink doesn't do anything in ReturnBuffer, so don't bother calling it.
- return bytes_to_read;
-}
-
-off64_t CompressedSnapshotReader::Seek(off64_t offset, int whence) {
- switch (whence) {
- case SEEK_SET:
- offset_ = offset;
- break;
- case SEEK_END:
- offset_ = static_cast<off64_t>(block_device_size_) + offset;
- break;
- case SEEK_CUR:
- offset_ += offset;
- break;
- default:
- LOG(ERROR) << "Unrecognized seek whence: " << whence;
- errno = EINVAL;
- return -1;
- }
- return offset_;
-}
-
-uint64_t CompressedSnapshotReader::BlockDevSize() {
- return block_device_size_;
-}
-
-bool CompressedSnapshotReader::Close() {
- cow_ = nullptr;
- source_fd_ = {};
- return true;
-}
-
-bool CompressedSnapshotReader::IsSettingErrno() {
- return true;
-}
-
-bool CompressedSnapshotReader::IsOpen() {
- return cow_ != nullptr;
-}
-
-bool CompressedSnapshotReader::Flush() {
- return true;
-}
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp
index 84e2226..9354102 100644
--- a/fs_mgr/libsnapshot/snapshot_stub.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stub.cpp
@@ -154,8 +154,8 @@
return &snapshot_merge_stats;
}
-std::unique_ptr<ISnapshotWriter> SnapshotManagerStub::OpenSnapshotWriter(
- const CreateLogicalPartitionParams&, const std::optional<std::string>&) {
+std::unique_ptr<ICowWriter> SnapshotManagerStub::OpenSnapshotWriter(
+ const CreateLogicalPartitionParams&, std::optional<uint64_t>) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return nullptr;
}
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 2c01cf6..0a85489 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -19,6 +19,7 @@
#include <signal.h>
#include <sys/file.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/types.h>
#include <chrono>
@@ -53,7 +54,15 @@
#include <libsnapshot/mock_device_info.h>
#include <libsnapshot/mock_snapshot.h>
-DEFINE_string(force_mode, "",
+#if defined(LIBSNAPSHOT_TEST_VAB_LEGACY)
+#define DEFAULT_MODE "vab-legacy"
+#elif defined(LIBSNAPSHOT_TEST_VABC_LEGACY)
+#define DEFAULT_MODE "vabc-legacy"
+#else
+#define DEFAULT_MODE ""
+#endif
+
+DEFINE_string(force_mode, DEFAULT_MODE,
"Force testing older modes (vab-legacy, vabc-legacy) ignoring device config.");
DEFINE_string(force_iouring_disable, "",
"Force testing mode (iouring_disabled) - disable io_uring");
@@ -116,6 +125,10 @@
SKIP_IF_NON_VIRTUAL_AB();
SetupProperties();
+ if (!DeviceSupportsMode()) {
+ GTEST_SKIP() << "Mode not supported on this device";
+ }
+
InitializeState();
CleanupTestArtifacts();
FormatFakeSuper();
@@ -151,7 +164,13 @@
IPropertyFetcher::OverrideForTesting(std::move(fetcher));
if (GetLegacyCompressionEnabledProperty() || CanUseUserspaceSnapshots()) {
- snapuserd_required_ = true;
+ // If we're asked to test the device's actual configuration, then it
+ // may be misconfigured, so check for kernel support as libsnapshot does.
+ if (FLAGS_force_mode.empty()) {
+ snapuserd_required_ = KernelSupportsCompressedSnapshots();
+ } else {
+ snapuserd_required_ = true;
+ }
}
}
@@ -168,6 +187,27 @@
LOG(INFO) << "Teardown complete for test: " << test_name_;
}
+ bool DeviceSupportsMode() {
+ if (FLAGS_force_mode.empty()) {
+ return true;
+ }
+ if (snapuserd_required_ && !KernelSupportsCompressedSnapshots()) {
+ return false;
+ }
+ return true;
+ }
+
+ bool ShouldSkipLegacyMerging() {
+ if (!GetLegacyCompressionEnabledProperty() || !snapuserd_required_) {
+ return false;
+ }
+ int api_level = android::base::GetIntProperty("ro.board.api_level", -1);
+ if (api_level == -1) {
+ api_level = android::base::GetIntProperty("ro.product.first_api_level", -1);
+ }
+ return api_level != __ANDROID_API_S__;
+ }
+
void InitializeState() {
ASSERT_TRUE(sm->EnsureImageManager());
image_manager_ = sm->image_manager();
@@ -185,6 +225,11 @@
// get an accurate list to remove.
lock_ = nullptr;
+ // If there is no image manager, the test was skipped.
+ if (!image_manager_) {
+ return;
+ }
+
std::vector<std::string> snapshots = {"test-snapshot", "test_partition_a",
"test_partition_b"};
for (const auto& snapshot : snapshots) {
@@ -300,7 +345,7 @@
}
AssertionResult MapUpdateSnapshot(const std::string& name,
- std::unique_ptr<ISnapshotWriter>* writer) {
+ std::unique_ptr<ICowWriter>* writer) {
TestPartitionOpener opener(fake_super);
CreateLogicalPartitionParams params{
.block_device = fake_super,
@@ -310,14 +355,10 @@
.partition_opener = &opener,
};
- auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name);
- auto result = sm->OpenSnapshotWriter(params, {old_partition});
+ auto result = sm->OpenSnapshotWriter(params, {});
if (!result) {
return AssertionFailure() << "Cannot open snapshot for writing: " << name;
}
- if (!result->Initialize()) {
- return AssertionFailure() << "Cannot initialize snapshot for writing: " << name;
- }
if (writer) {
*writer = std::move(result);
@@ -395,7 +436,7 @@
// Prepare A/B slot for a partition named "test_partition".
AssertionResult PrepareOneSnapshot(uint64_t device_size,
- std::unique_ptr<ISnapshotWriter>* writer = nullptr) {
+ std::unique_ptr<ICowWriter>* writer = nullptr) {
lock_ = nullptr;
DeltaArchiveManifest manifest;
@@ -598,21 +639,38 @@
TEST_F(SnapshotTest, Merge) {
ASSERT_TRUE(AcquireLock());
- static const uint64_t kDeviceSize = 1024 * 1024;
-
- std::unique_ptr<ISnapshotWriter> writer;
- ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &writer));
-
- bool userspace_snapshots = sm->UpdateUsesUserSnapshots(lock_.get());
-
- // Release the lock.
- lock_ = nullptr;
+ static constexpr uint64_t kDeviceSize = 1024 * 1024;
+ static constexpr uint32_t kBlockSize = 4096;
std::string test_string = "This is a test string.";
- test_string.resize(writer->options().block_size);
- ASSERT_TRUE(writer->AddRawBlocks(0, test_string.data(), test_string.size()));
- ASSERT_TRUE(writer->Finalize());
- writer = nullptr;
+ test_string.resize(kBlockSize);
+
+ bool userspace_snapshots = false;
+ if (snapuserd_required_) {
+ std::unique_ptr<ICowWriter> writer;
+ ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &writer));
+
+ userspace_snapshots = sm->UpdateUsesUserSnapshots(lock_.get());
+
+ // Release the lock.
+ lock_ = nullptr;
+
+ ASSERT_TRUE(writer->AddRawBlocks(0, test_string.data(), test_string.size()));
+ ASSERT_TRUE(writer->Finalize());
+ writer = nullptr;
+ } else {
+ ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
+
+ // Release the lock.
+ lock_ = nullptr;
+
+ std::string path;
+ ASSERT_TRUE(dm_.GetDmDevicePathByName("test_partition_b", &path));
+
+ unique_fd fd(open(path.c_str(), O_WRONLY));
+ ASSERT_GE(fd, 0);
+ ASSERT_TRUE(android::base::WriteFully(fd, test_string.data(), test_string.size()));
+ }
// Done updating.
ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
@@ -621,6 +679,10 @@
test_device->set_slot_suffix("_b");
ASSERT_TRUE(sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(sm->InitiateMerge());
// The device should have been switched to a snapshot-merge target.
@@ -728,6 +790,10 @@
ASSERT_NE(init, nullptr);
ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
// Now, reflash super. Note that we haven't called ProcessUpdateState, so the
@@ -938,6 +1004,11 @@
SKIP_IF_NON_VIRTUAL_AB();
SnapshotTest::SetUp();
+ if (!image_manager_) {
+ // Test was skipped.
+ return;
+ }
+
Cleanup();
// Cleanup() changes slot suffix, so initialize it again.
@@ -1085,7 +1156,7 @@
AssertionResult MapOneUpdateSnapshot(const std::string& name) {
if (snapuserd_required_) {
- std::unique_ptr<ISnapshotWriter> writer;
+ std::unique_ptr<ICowWriter> writer;
return MapUpdateSnapshot(name, &writer);
} else {
std::string path;
@@ -1106,7 +1177,7 @@
AssertionResult WriteSnapshotAndHash(PartitionUpdate* partition) {
std::string name = partition->partition_name() + "_b";
if (snapuserd_required_) {
- std::unique_ptr<ISnapshotWriter> writer;
+ std::unique_ptr<ICowWriter> writer;
auto res = MapUpdateSnapshot(name, &writer);
if (!res) {
return res;
@@ -1145,13 +1216,13 @@
SHA256_CTX ctx;
SHA256_Init(&ctx);
- if (!writer->options().max_blocks) {
+ if (!writer->GetMaxBlocks()) {
LOG(ERROR) << "CowWriter must specify maximum number of blocks";
return false;
}
- const auto num_blocks = writer->options().max_blocks.value();
+ const auto num_blocks = writer->GetMaxBlocks().value();
- const auto block_size = writer->options().block_size;
+ const auto block_size = writer->GetBlockSize();
std::string block(block_size, '\0');
for (uint64_t i = 0; i < num_blocks; i++) {
if (!ReadFully(rand, block.data(), block.size())) {
@@ -1175,17 +1246,17 @@
// It doesn't really matter the order, we just want copies that reference
// blocks that won't exist if the partition shrinks.
AssertionResult ShiftAllSnapshotBlocks(const std::string& name, uint64_t old_size) {
- std::unique_ptr<ISnapshotWriter> writer;
+ std::unique_ptr<ICowWriter> writer;
if (auto res = MapUpdateSnapshot(name, &writer); !res) {
return res;
}
- if (!writer->options().max_blocks || !*writer->options().max_blocks) {
+ if (!writer->GetMaxBlocks() || !*writer->GetMaxBlocks()) {
return AssertionFailure() << "No max blocks set for " << name << " writer";
}
- uint64_t src_block = (old_size / writer->options().block_size) - 1;
+ uint64_t src_block = (old_size / writer->GetBlockSize()) - 1;
uint64_t dst_block = 0;
- uint64_t max_blocks = *writer->options().max_blocks;
+ uint64_t max_blocks = *writer->GetMaxBlocks();
while (dst_block < max_blocks && dst_block < src_block) {
if (!writer->AddCopy(dst_block, src_block)) {
return AssertionFailure() << "Unable to add copy for " << name << " for blocks "
@@ -1198,7 +1269,13 @@
return AssertionFailure() << "Unable to finalize writer for " << name;
}
- auto hash = HashSnapshot(writer.get());
+ auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name);
+ auto reader = writer->OpenFileDescriptor(old_partition);
+ if (!reader) {
+ return AssertionFailure() << "Could not open file descriptor for " << name;
+ }
+
+ auto hash = HashSnapshot(reader.get());
if (hash.empty()) {
return AssertionFailure() << "Unable to hash snapshot writer for " << name;
}
@@ -1306,6 +1383,10 @@
}
// Initiate the merge and wait for it to be completed.
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
{
@@ -1349,7 +1430,7 @@
for (auto* partition : partitions) {
AddOperation(partition);
- std::unique_ptr<ISnapshotWriter> writer;
+ std::unique_ptr<ICowWriter> writer;
auto res = MapUpdateSnapshot(partition->partition_name() + "_b", &writer);
ASSERT_TRUE(res);
ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
@@ -1369,6 +1450,10 @@
ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
// Initiate the merge and wait for it to be completed.
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
}
@@ -1438,6 +1523,10 @@
}
// Initiate the merge and wait for it to be completed.
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
{
@@ -1546,6 +1635,10 @@
});
// Initiate the merge and wait for it to be completed.
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
{
@@ -1748,6 +1841,10 @@
// Initiate the merge and wait for it to be completed.
auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(new_sm->InitiateMerge());
ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
@@ -1886,6 +1983,10 @@
ASSERT_GE(fd, 0);
// COW cannot be removed due to open fd, so expect a soft failure.
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(UpdateState::MergeNeedsReboot, init->ProcessUpdateState());
@@ -1989,6 +2090,10 @@
// Initiate the merge and then immediately stop it to simulate a reboot.
auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(new_sm->InitiateMerge());
ASSERT_TRUE(UnmapAll());
@@ -2021,6 +2126,10 @@
// Initiate the merge and then immediately stop it to simulate a reboot.
auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(new_sm->InitiateMerge());
ASSERT_TRUE(UnmapAll());
@@ -2098,6 +2207,10 @@
// Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest, DataWipeRequiredInPackage) {
+ if (ShouldSkipLegacyMerging()) {
+ GTEST_SKIP() << "Skipping legacy merge in test";
+ }
+
AddOperationForPartitions();
// Execute the update.
ASSERT_TRUE(sm->BeginUpdate());
@@ -2137,6 +2250,10 @@
// Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest, DataWipeWithStaleSnapshots) {
+ if (ShouldSkipLegacyMerging()) {
+ GTEST_SKIP() << "Skipping legacy merge in test";
+ }
+
AddOperationForPartitions();
// Execute the update.
@@ -2274,32 +2391,6 @@
<< "FinishedSnapshotWrites should detect overflow of CoW device.";
}
-TEST_F(SnapshotUpdateTest, LowSpace) {
- static constexpr auto kMaxFree = 10_MiB;
- auto userdata = std::make_unique<LowSpaceUserdata>();
- ASSERT_TRUE(userdata->Init(kMaxFree));
-
- // Grow all partitions to 10_MiB, total 30_MiB. This requires 30 MiB of CoW space. After
- // using the empty space in super (< 1 MiB), it uses 30 MiB of /userdata space.
- constexpr uint64_t partition_size = 10_MiB;
- SetSize(sys_, partition_size);
- SetSize(vnd_, partition_size);
- SetSize(prd_, partition_size);
- sys_->set_estimate_cow_size(partition_size);
- vnd_->set_estimate_cow_size(partition_size);
- prd_->set_estimate_cow_size(partition_size);
-
- AddOperationForPartitions();
-
- // Execute the update.
- ASSERT_TRUE(sm->BeginUpdate());
- auto res = sm->CreateUpdateSnapshots(manifest_);
- ASSERT_FALSE(res);
- ASSERT_EQ(Return::ErrorCode::NO_SPACE, res.error_code());
- ASSERT_GE(res.required_size(), 14_MiB);
- ASSERT_LT(res.required_size(), 40_MiB);
-}
-
TEST_F(SnapshotUpdateTest, AddPartition) {
group_->add_partition_names("dlkm");
@@ -2359,6 +2450,10 @@
}
// Initiate the merge and wait for it to be completed.
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
@@ -2545,6 +2640,11 @@
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(UpdateState::MergeFailed, init->ProcessUpdateState());
+ if (ShouldSkipLegacyMerging()) {
+ LOG(INFO) << "Skipping legacy merge in test";
+ return;
+ }
+
// Simulate a reboot that tries the merge again, with the non-failing dm.
ASSERT_TRUE(UnmapAll());
init = NewManagerForFirstStageMount("_b");
@@ -2553,6 +2653,24 @@
ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
}
+TEST_F(SnapshotUpdateTest, BadCowVersion) {
+ if (!snapuserd_required_) {
+ GTEST_SKIP() << "VABC only";
+ }
+
+ ASSERT_TRUE(sm->BeginUpdate());
+
+ auto dynamic_partition_metadata = manifest_.mutable_dynamic_partition_metadata();
+ dynamic_partition_metadata->set_cow_version(kMinCowVersion - 1);
+ ASSERT_FALSE(sm->CreateUpdateSnapshots(manifest_));
+
+ dynamic_partition_metadata->set_cow_version(kMaxCowVersion + 1);
+ ASSERT_FALSE(sm->CreateUpdateSnapshots(manifest_));
+
+ dynamic_partition_metadata->set_cow_version(kMaxCowVersion);
+ ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+}
+
class FlashAfterUpdateTest : public SnapshotUpdateTest,
public WithParamInterface<std::tuple<uint32_t, bool>> {
public:
@@ -2661,45 +2779,6 @@
"Merge"s;
});
-// Test behavior of ImageManager::Create on low space scenario. These tests assumes image manager
-// uses /data as backup device.
-class ImageManagerTest : public SnapshotTest, public WithParamInterface<uint64_t> {
- protected:
- void SetUp() override {
- SKIP_IF_NON_VIRTUAL_AB();
- SnapshotTest::SetUp();
- userdata_ = std::make_unique<LowSpaceUserdata>();
- ASSERT_TRUE(userdata_->Init(GetParam()));
- }
- void TearDown() override {
- RETURN_IF_NON_VIRTUAL_AB();
-
- EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) ||
- image_manager_->DeleteBackingImage(kImageName));
- }
- static constexpr const char* kImageName = "my_image";
- std::unique_ptr<LowSpaceUserdata> userdata_;
-};
-
-TEST_P(ImageManagerTest, CreateImageNoSpace) {
- uint64_t to_allocate = userdata_->free_space() + userdata_->bsize();
- auto res = image_manager_->CreateBackingImage(kImageName, to_allocate,
- IImageManager::CREATE_IMAGE_DEFAULT);
- ASSERT_FALSE(res) << "Should not be able to create image with size = " << to_allocate
- << " bytes because only " << userdata_->free_space() << " bytes are free";
- ASSERT_EQ(FiemapStatus::ErrorCode::NO_SPACE, res.error_code()) << res.string();
-}
-
-std::vector<uint64_t> ImageManagerTestParams() {
- std::vector<uint64_t> ret;
- for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) {
- ret.push_back(size);
- }
- return ret;
-}
-
-INSTANTIATE_TEST_SUITE_P(ImageManagerTest, ImageManagerTest, ValuesIn(ImageManagerTestParams()));
-
bool Mkdir(const std::string& path) {
if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
deleted file mode 100644
index 82a7fd7..0000000
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-//
-// Copyright (C) 2020 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 <libsnapshot/snapshot_writer.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <payload_consumer/file_descriptor.h>
-#include "snapshot_reader.h"
-
-namespace android {
-namespace snapshot {
-
-using android::base::borrowed_fd;
-using android::base::unique_fd;
-using chromeos_update_engine::FileDescriptor;
-
-ISnapshotWriter::ISnapshotWriter(const CowOptions& options) : ICowWriter(options) {}
-
-void ISnapshotWriter::SetSourceDevice(const std::string& source_device) {
- source_device_ = {source_device};
-}
-
-borrowed_fd ISnapshotWriter::GetSourceFd() {
- if (!source_device_) {
- LOG(ERROR) << "Attempted to read from source device but none was set";
- return borrowed_fd{-1};
- }
-
- if (source_fd_ < 0) {
- source_fd_.reset(open(source_device_->c_str(), O_RDONLY | O_CLOEXEC));
- if (source_fd_ < 0) {
- PLOG(ERROR) << "open " << *source_device_;
- return borrowed_fd{-1};
- }
- }
- return source_fd_;
-}
-
-CompressedSnapshotWriter::CompressedSnapshotWriter(const CowOptions& options)
- : ISnapshotWriter(options) {}
-
-bool CompressedSnapshotWriter::SetCowDevice(android::base::unique_fd&& cow_device) {
- cow_device_ = std::move(cow_device);
- cow_ = std::make_unique<CowWriter>(options_);
- return true;
-}
-
-bool CompressedSnapshotWriter::Finalize() {
- return cow_->Finalize();
-}
-
-uint64_t CompressedSnapshotWriter::GetCowSize() {
- return cow_->GetCowSize();
-}
-
-std::unique_ptr<CowReader> CompressedSnapshotWriter::OpenCowReader() const {
- unique_fd cow_fd(dup(cow_device_.get()));
- if (cow_fd < 0) {
- PLOG(ERROR) << "dup COW device";
- return nullptr;
- }
-
- auto cow = std::make_unique<CowReader>();
- if (!cow->Parse(std::move(cow_fd))) {
- LOG(ERROR) << "Unable to read COW";
- return nullptr;
- }
- return cow;
-}
-
-bool CompressedSnapshotWriter::VerifyMergeOps() const noexcept {
- auto cow_reader = OpenCowReader();
- if (cow_reader == nullptr) {
- LOG(ERROR) << "Couldn't open CowReader";
- return false;
- }
- return cow_reader->VerifyMergeOps();
-}
-
-std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() {
- auto cow = OpenCowReader();
- if (cow == nullptr) {
- return nullptr;
- }
-
- auto reader = std::make_unique<CompressedSnapshotReader>();
- if (!reader->SetCow(std::move(cow))) {
- LOG(ERROR) << "Unable to initialize COW reader";
- return nullptr;
- }
- if (source_device_) {
- reader->SetSourceDevice(*source_device_);
- }
-
- const auto& cow_options = options();
- if (cow_options.max_blocks) {
- reader->SetBlockDeviceSize(*cow_options.max_blocks * cow_options.block_size);
- }
-
- return reader;
-}
-
-bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block,
- uint64_t num_blocks) {
- return cow_->AddCopy(new_block, old_block, num_blocks);
-}
-
-bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data,
- size_t size) {
- return cow_->AddRawBlocks(new_block_start, data, size);
-}
-
-bool CompressedSnapshotWriter::EmitXorBlocks(uint32_t new_block_start, const void* data,
- size_t size, uint32_t old_block, uint16_t offset) {
- return cow_->AddXorBlocks(new_block_start, data, size, old_block, offset);
-}
-
-bool CompressedSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
- return cow_->AddZeroBlocks(new_block_start, num_blocks);
-}
-
-bool CompressedSnapshotWriter::EmitLabel(uint64_t label) {
- return cow_->AddLabel(label);
-}
-
-bool CompressedSnapshotWriter::EmitSequenceData(size_t num_ops, const uint32_t* data) {
- return cow_->AddSequenceData(num_ops, data);
-}
-
-bool CompressedSnapshotWriter::Initialize() {
- return cow_->Initialize(cow_device_);
-}
-
-bool CompressedSnapshotWriter::InitializeAppend(uint64_t label) {
- return cow_->InitializeAppend(cow_device_, label);
-}
-
-OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options)
- : ISnapshotWriter(options) {}
-
-void OnlineKernelSnapshotWriter::SetSnapshotDevice(android::base::unique_fd&& snapshot_fd,
- uint64_t cow_size) {
- snapshot_fd_ = std::move(snapshot_fd);
- cow_size_ = cow_size;
-}
-
-bool OnlineKernelSnapshotWriter::Finalize() {
- if (fsync(snapshot_fd_.get()) < 0) {
- PLOG(ERROR) << "fsync";
- return false;
- }
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data,
- size_t size) {
- uint64_t offset = new_block_start * options_.block_size;
- if (lseek(snapshot_fd_.get(), offset, SEEK_SET) < 0) {
- PLOG(ERROR) << "EmitRawBlocks lseek to offset " << offset;
- return false;
- }
- if (!android::base::WriteFully(snapshot_fd_, data, size)) {
- PLOG(ERROR) << "EmitRawBlocks write";
- return false;
- }
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitXorBlocks(uint32_t, const void*, size_t, uint32_t, uint16_t) {
- LOG(ERROR) << "EmitXorBlocks not implemented.";
- return false;
-}
-
-bool OnlineKernelSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
- std::string zeroes(options_.block_size, 0);
- for (uint64_t i = 0; i < num_blocks; i++) {
- if (!EmitRawBlocks(new_block_start + i, zeroes.data(), zeroes.size())) {
- return false;
- }
- }
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block,
- uint64_t num_blocks) {
- auto source_fd = GetSourceFd();
- if (source_fd < 0) {
- return false;
- }
-
- CHECK(num_blocks != 0);
-
- for (size_t i = 0; i < num_blocks; i++) {
- std::string buffer(options_.block_size, 0);
- uint64_t offset = (old_block + i) * options_.block_size;
- if (!android::base::ReadFullyAtOffset(source_fd, buffer.data(), buffer.size(), offset)) {
- PLOG(ERROR) << "EmitCopy read";
- return false;
- }
- if (!EmitRawBlocks(new_block + i, buffer.data(), buffer.size())) {
- PLOG(ERROR) << "EmitRawBlocks failed";
- return false;
- }
- }
-
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitLabel(uint64_t) {
- // Not Needed
- return true;
-}
-
-bool OnlineKernelSnapshotWriter::EmitSequenceData(size_t, const uint32_t*) {
- // Not Needed
- return true;
-}
-
-std::unique_ptr<FileDescriptor> OnlineKernelSnapshotWriter::OpenReader() {
- unique_fd fd(dup(snapshot_fd_.get()));
- if (fd < 0) {
- PLOG(ERROR) << "dup2 failed in OpenReader";
- return nullptr;
- }
- return std::make_unique<ReadFdFileDescriptor>(std::move(fd));
-}
-
-} // namespace snapshot
-} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_writer_test.cpp b/fs_mgr/libsnapshot/snapshot_writer_test.cpp
deleted file mode 100644
index da48eb9..0000000
--- a/fs_mgr/libsnapshot/snapshot_writer_test.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 2021 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 <libsnapshot/snapshot.h>
-
-#include <unordered_set>
-
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-#include <libsnapshot/snapshot_writer.h>
-#include <payload_consumer/file_descriptor.h>
-
-namespace android::snapshot {
-class CompressedSnapshotWriterTest : public ::testing::Test {
- public:
- static constexpr size_t BLOCK_SIZE = 4096;
-};
-
-TEST_F(CompressedSnapshotWriterTest, ReadAfterWrite) {
- TemporaryFile cow_device_file{};
- android::snapshot::CowOptions options{.block_size = BLOCK_SIZE};
- android::snapshot::CompressedSnapshotWriter snapshot_writer{options};
- snapshot_writer.SetCowDevice(android::base::unique_fd{cow_device_file.fd});
- snapshot_writer.Initialize();
- std::vector<unsigned char> buffer;
- buffer.resize(BLOCK_SIZE);
- std::fill(buffer.begin(), buffer.end(), 123);
-
- ASSERT_TRUE(snapshot_writer.AddRawBlocks(0, buffer.data(), buffer.size()));
- ASSERT_TRUE(snapshot_writer.Finalize());
- auto cow_reader = snapshot_writer.OpenReader();
- ASSERT_NE(cow_reader, nullptr);
- ASSERT_TRUE(snapshot_writer.AddRawBlocks(1, buffer.data(), buffer.size()));
- ASSERT_TRUE(snapshot_writer.AddRawBlocks(2, buffer.data(), buffer.size()));
- ASSERT_TRUE(snapshot_writer.Finalize());
- // After wrigin some data, if we call OpenReader() again, writes should
- // be visible to the newly opened reader. update_engine relies on this
- // behavior for verity writes.
- cow_reader = snapshot_writer.OpenReader();
- ASSERT_NE(cow_reader, nullptr);
- std::vector<unsigned char> read_back;
- read_back.resize(buffer.size());
- cow_reader->Seek(BLOCK_SIZE, SEEK_SET);
- const auto bytes_read = cow_reader->Read(read_back.data(), read_back.size());
- ASSERT_EQ((size_t)(bytes_read), BLOCK_SIZE);
- ASSERT_EQ(read_back, buffer);
-}
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index ad3f83c..38eb719 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -133,7 +133,6 @@
// Write the "new" system partition.
auto system_target_name = "system" + target_slot;
- auto source_device = "/dev/block/mapper/" + system_source_name;
CreateLogicalPartitionParams clpp = {
.block_device = fs_mgr_get_super_partition_name(target_slot_number),
.metadata_slot = {target_slot_number},
@@ -141,15 +140,11 @@
.partition_opener = &opener,
.timeout_ms = 10s,
};
- auto writer = sm->OpenSnapshotWriter(clpp, {source_device});
+ auto writer = sm->OpenSnapshotWriter(clpp, std::nullopt);
if (!writer) {
std::cerr << "Could not open snapshot writer.\n";
return false;
}
- if (!writer->Initialize()) {
- std::cerr << "Could not initialize snapshot for writing.\n";
- return false;
- }
for (uint64_t block = 0; block < system_source_size / 4096; block++) {
if (!writer->AddCopy(block, block)) {
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 64e0b8a..9fe567a 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -25,8 +25,6 @@
],
cflags: [
"-D_FILE_OFFSET_BITS=64",
- "-Wall",
- "-Werror",
],
export_include_dirs: ["include"],
srcs: [
@@ -37,11 +35,13 @@
cc_library_static {
name: "libsnapshot_snapuserd",
defaults: [
+ "fs_mgr_defaults",
"libsnapshot_snapuserd_defaults",
],
recovery_available: true,
static_libs: [
"libcutils_sockets",
+ "libfs_mgr",
],
shared_libs: [
"libbase",
@@ -49,6 +49,41 @@
],
export_include_dirs: ["include"],
ramdisk_available: true,
+ vendor_ramdisk_available: true,
+}
+
+cc_library_static {
+ name: "libsnapuserd",
+ defaults: [
+ "fs_mgr_defaults",
+ ],
+ 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/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",
+ ],
+ static_libs: [
+ "libbase",
+ "libdm",
+ "libext4_utils",
+ "libsnapshot_cow",
+ "liburing",
+ ],
+ include_dirs: ["bionic/libc/kernel"],
+ header_libs: [
+ "libstorage_literals_headers",
+ ],
+ ramdisk_available: true,
+ vendor_ramdisk_available: true,
+ recovery_available: true,
}
cc_defaults {
@@ -58,23 +93,8 @@
],
srcs: [
"dm-snapshot-merge/snapuserd_server.cpp",
- "dm-snapshot-merge/snapuserd.cpp",
- "dm-snapshot-merge/snapuserd_worker.cpp",
- "dm-snapshot-merge/snapuserd_readahead.cpp",
"snapuserd_daemon.cpp",
- "snapuserd_buffer.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_server.cpp",
- "user-space-merge/snapuserd_verify.cpp",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
],
static_libs: [
@@ -86,10 +106,13 @@
"libgflags",
"liblog",
"libsnapshot_cow",
+ "libsnapshot_snapuserd",
+ "libsnapuserd",
"libz",
"liblz4",
"libext4_utils",
"liburing",
+ "libzstd",
],
header_libs: [
@@ -121,7 +144,6 @@
],
ramdisk_available: false,
vendor_ramdisk_available: true,
- recovery_available: true,
}
// This target will install to /system/bin/snapuserd_ramdisk
@@ -143,7 +165,7 @@
}
cc_test {
- name: "cow_snapuserd_test",
+ name: "snapuserd_test_legacy",
defaults: [
"fs_mgr_defaults",
"libsnapshot_cow_defaults",
@@ -154,10 +176,6 @@
"dm-snapshot-merge/snapuserd_worker.cpp",
"snapuserd_buffer.cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
"libbase",
"liblog",
@@ -193,26 +211,23 @@
srcs: [
"user-space-merge/snapuserd_test.cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
"libbase",
"liblog",
],
static_libs: [
"libbrotli",
+ "libcutils_sockets",
+ "libdm",
+ "libext4_utils",
+ "libfs_mgr",
+ "libgflags",
"libgtest",
"libsnapshot_cow",
"libsnapshot_snapuserd",
- "libcutils_sockets",
- "libz",
- "libfs_mgr",
- "libdm",
- "libext4_utils",
+ "libsnapuserd",
"liburing",
- "libgflags",
+ "libz",
],
include_dirs: ["bionic/libc/kernel"],
header_libs: [
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/cow_snapuserd_test.cpp
index 484a9c4..737c480 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/cow_snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/cow_snapuserd_test.cpp
@@ -122,6 +122,7 @@
void SimulateDaemonRestart();
void StartMerge();
+ std::unique_ptr<ICowWriter> CreateCowDeviceInternal();
void CreateCowDevice();
void CreateCowDeviceOrderedOps();
void CreateCowDeviceOrderedOpsInverted();
@@ -164,6 +165,7 @@
private:
void InitMetadata();
+ std::unique_ptr<ICowWriter> CreateCowDeviceInternal();
void CreateCowDevice();
void CreateCowPartialFilledArea();
@@ -258,6 +260,19 @@
}
}
+std::unique_ptr<ICowWriter> CowSnapuserdTest::CreateCowDeviceInternal() {
+ std::string path = android::base::GetExecutableDirectory();
+ cow_system_ = std::make_unique<TemporaryFile>(path);
+
+ CowOptions options;
+ options.compression = "gz";
+
+ unique_fd fd(cow_system_->fd);
+ cow_system_->fd = -1;
+
+ return CreateCowWriter(kDefaultCowVersion, options, std::move(fd));
+}
+
void CowSnapuserdTest::ReadLastBlock() {
unique_fd rnd_fd;
total_base_size_ = BLOCK_SZ * 2;
@@ -280,9 +295,6 @@
base_loop_ = std::make_unique<LoopDevice>(base_fd_, 10s);
ASSERT_TRUE(base_loop_->valid());
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
-
std::unique_ptr<uint8_t[]> random_buffer_1_ = std::make_unique<uint8_t[]>(total_base_size_);
loff_t offset = 0;
@@ -294,16 +306,13 @@
offset += BLOCK_SZ;
}
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
+ ASSERT_TRUE(writer->AddRawBlocks(0, random_buffer_1_.get(), BLOCK_SZ));
+ ASSERT_TRUE(writer->AddRawBlocks(1, (char*)random_buffer_1_.get() + BLOCK_SZ, BLOCK_SZ));
- ASSERT_TRUE(writer.AddRawBlocks(0, random_buffer_1_.get(), BLOCK_SZ));
- ASSERT_TRUE(writer.AddRawBlocks(1, (char*)random_buffer_1_.get() + BLOCK_SZ, BLOCK_SZ));
-
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
SetDeviceControlName();
@@ -381,22 +390,16 @@
}
void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_2() {
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t x = num_blocks;
size_t blk_src_copy = 0;
// Create overlapping copy operations
while (1) {
- ASSERT_TRUE(writer.AddCopy(blk_src_copy, blk_src_copy + 1));
+ ASSERT_TRUE(writer->AddCopy(blk_src_copy, blk_src_copy + 1));
x -= 1;
if (x == 1) {
break;
@@ -405,7 +408,7 @@
}
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
@@ -433,22 +436,16 @@
}
void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_1() {
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t x = num_blocks;
size_t blk_src_copy = num_blocks - 1;
// Create overlapping copy operations
while (1) {
- ASSERT_TRUE(writer.AddCopy(blk_src_copy + 1, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(blk_src_copy + 1, blk_src_copy));
x -= 1;
if (x == 0) {
ASSERT_EQ(blk_src_copy, 0);
@@ -458,7 +455,7 @@
}
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
@@ -468,10 +465,11 @@
true);
// Merged operations
- ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), options.block_size, 0),
+ ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), writer->GetBlockSize(),
+ 0),
true);
ASSERT_EQ(android::base::ReadFullyAtOffset(
- base_fd_, (char*)orig_buffer_.get() + options.block_size, size_, 0),
+ base_fd_, (char*)orig_buffer_.get() + writer->GetBlockSize(), size_, 0),
true);
}
@@ -479,8 +477,8 @@
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -495,13 +493,7 @@
offset += 1_MiB;
}
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t blk_end_copy = num_blocks * 3;
size_t source_blk = num_blocks - 1;
size_t blk_src_copy = blk_end_copy - 1;
@@ -509,7 +501,7 @@
size_t x = num_blocks;
while (1) {
- ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy));
x -= 1;
if (x == 0) {
break;
@@ -519,12 +511,12 @@
}
for (size_t i = num_blocks; i > 0; i--) {
- ASSERT_TRUE(writer.AddXorBlocks(num_blocks + i - 1,
- &random_buffer_1_.get()[options.block_size * (i - 1)],
- options.block_size, 2 * num_blocks + i - 1, xor_offset));
+ ASSERT_TRUE(writer->AddXorBlocks(
+ num_blocks + i - 1, &random_buffer_1_.get()[writer->GetBlockSize() * (i - 1)],
+ writer->GetBlockSize(), 2 * num_blocks + i - 1, xor_offset));
}
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
// Read the entire base device
@@ -542,8 +534,8 @@
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -559,20 +551,14 @@
}
memset(random_buffer_1_.get(), 0, size_);
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t x = num_blocks;
size_t source_blk = 0;
size_t blk_src_copy = 2 * num_blocks;
uint16_t xor_offset = 5;
while (1) {
- ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy));
x -= 1;
if (x == 0) {
@@ -582,10 +568,10 @@
blk_src_copy += 1;
}
- ASSERT_TRUE(writer.AddXorBlocks(num_blocks, random_buffer_1_.get(), size_, 2 * num_blocks,
- xor_offset));
+ ASSERT_TRUE(writer->AddXorBlocks(num_blocks, random_buffer_1_.get(), size_, 2 * num_blocks,
+ xor_offset));
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
// Read the entire base device
@@ -603,8 +589,8 @@
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -619,13 +605,7 @@
offset += 1_MiB;
}
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t blk_end_copy = num_blocks * 2;
size_t source_blk = num_blocks - 1;
size_t blk_src_copy = blk_end_copy - 1;
@@ -639,11 +619,11 @@
for (int i = 0; i < num_blocks; i++) {
sequence[num_blocks + i] = 5 * num_blocks - 1 - i;
}
- ASSERT_TRUE(writer.AddSequenceData(2 * num_blocks, sequence));
+ ASSERT_TRUE(writer->AddSequenceData(2 * num_blocks, sequence));
size_t x = num_blocks;
while (1) {
- ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy));
x -= 1;
if (x == 0) {
break;
@@ -655,24 +635,24 @@
source_blk = num_blocks;
blk_src_copy = blk_end_copy;
- ASSERT_TRUE(writer.AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
+ ASSERT_TRUE(writer->AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
size_t blk_zero_copy_start = source_blk + num_blocks;
size_t blk_zero_copy_end = blk_zero_copy_start + num_blocks;
- ASSERT_TRUE(writer.AddZeroBlocks(blk_zero_copy_start, num_blocks));
+ ASSERT_TRUE(writer->AddZeroBlocks(blk_zero_copy_start, num_blocks));
size_t blk_random2_replace_start = blk_zero_copy_end;
- ASSERT_TRUE(writer.AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_));
+ ASSERT_TRUE(writer->AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_));
size_t blk_xor_start = blk_random2_replace_start + num_blocks;
size_t xor_offset = BLOCK_SZ / 2;
- ASSERT_TRUE(writer.AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks,
- xor_offset));
+ ASSERT_TRUE(writer->AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks,
+ xor_offset));
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
std::string zero_buffer(size_, 0);
@@ -902,29 +882,36 @@
ASSERT_TRUE(Merge());
}
-void CowSnapuserdMetadataTest::CreateCowPartialFilledArea() {
+std::unique_ptr<ICowWriter> CowSnapuserdMetadataTest::CreateCowDeviceInternal() {
std::string path = android::base::GetExecutableDirectory();
cow_system_ = std::make_unique<TemporaryFile>(path);
CowOptions options;
options.compression = "gz";
- CowWriter writer(options);
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
+ unique_fd fd(cow_system_->fd);
+ cow_system_->fd = -1;
+
+ return CreateCowWriter(kDefaultCowVersion, options, std::move(fd));
+}
+
+void CowSnapuserdMetadataTest::CreateCowPartialFilledArea() {
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
// Area 0 is completely filled with 256 exceptions
for (int i = 0; i < 256; i++) {
- ASSERT_TRUE(writer.AddCopy(i, 256 + i));
+ ASSERT_TRUE(writer->AddCopy(i, 256 + i));
}
// Area 1 is partially filled with 2 copy ops and 10 zero ops
- ASSERT_TRUE(writer.AddCopy(500, 1000));
- ASSERT_TRUE(writer.AddCopy(501, 1001));
+ ASSERT_TRUE(writer->AddCopy(500, 1000));
+ ASSERT_TRUE(writer->AddCopy(501, 1001));
- ASSERT_TRUE(writer.AddZeroBlocks(300, 10));
+ ASSERT_TRUE(writer->AddZeroBlocks(300, 10));
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
}
void CowSnapuserdMetadataTest::ValidatePartialFilledArea() {
@@ -956,8 +943,8 @@
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -972,50 +959,44 @@
offset += 1_MiB;
}
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
// Overlapping region. This has to be split
// into two batch operations
- ASSERT_TRUE(writer.AddCopy(23, 20));
- ASSERT_TRUE(writer.AddCopy(22, 19));
- ASSERT_TRUE(writer.AddCopy(21, 18));
- ASSERT_TRUE(writer.AddCopy(20, 17));
- ASSERT_TRUE(writer.AddCopy(19, 16));
- ASSERT_TRUE(writer.AddCopy(18, 15));
+ ASSERT_TRUE(writer->AddCopy(23, 20));
+ ASSERT_TRUE(writer->AddCopy(22, 19));
+ ASSERT_TRUE(writer->AddCopy(21, 18));
+ ASSERT_TRUE(writer->AddCopy(20, 17));
+ ASSERT_TRUE(writer->AddCopy(19, 16));
+ ASSERT_TRUE(writer->AddCopy(18, 15));
// Contiguous region but blocks in ascending order
// Daemon has to ensure that these blocks are merged
// in a batch
- ASSERT_TRUE(writer.AddCopy(50, 75));
- ASSERT_TRUE(writer.AddCopy(51, 76));
- ASSERT_TRUE(writer.AddCopy(52, 77));
- ASSERT_TRUE(writer.AddCopy(53, 78));
+ ASSERT_TRUE(writer->AddCopy(50, 75));
+ ASSERT_TRUE(writer->AddCopy(51, 76));
+ ASSERT_TRUE(writer->AddCopy(52, 77));
+ ASSERT_TRUE(writer->AddCopy(53, 78));
// Dis-contiguous region
- ASSERT_TRUE(writer.AddCopy(110, 130));
- ASSERT_TRUE(writer.AddCopy(105, 125));
- ASSERT_TRUE(writer.AddCopy(100, 120));
+ ASSERT_TRUE(writer->AddCopy(110, 130));
+ ASSERT_TRUE(writer->AddCopy(105, 125));
+ ASSERT_TRUE(writer->AddCopy(100, 120));
// Overlap
- ASSERT_TRUE(writer.AddCopy(25, 30));
- ASSERT_TRUE(writer.AddCopy(30, 31));
+ ASSERT_TRUE(writer->AddCopy(25, 30));
+ ASSERT_TRUE(writer->AddCopy(30, 31));
size_t source_blk = num_blocks;
- ASSERT_TRUE(writer.AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
+ ASSERT_TRUE(writer->AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
size_t blk_zero_copy_start = source_blk + num_blocks;
- ASSERT_TRUE(writer.AddZeroBlocks(blk_zero_copy_start, num_blocks));
+ ASSERT_TRUE(writer->AddZeroBlocks(blk_zero_copy_start, num_blocks));
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
}
void CowSnapuserdMetadataTest::InitMetadata() {
@@ -1152,35 +1133,6 @@
}
}
-TEST(Snapuserd_Test, xor_buffer) {
- std::string data = "Test String";
- std::string jumbled = {0x0C, 0x2A, 0x21, 0x54, 0x73, 0x27, 0x06, 0x1B, 0x07, 0x09, 0x46};
- std::string result = "XOR String!";
-
- BufferSink sink;
- XorSink xor_sink;
- sink.Initialize(sizeof(struct dm_user_header) + 10);
- int buffsize = 5;
- xor_sink.Initialize(&sink, buffsize);
-
- void* buff = sink.GetPayloadBuffer(data.length());
- memcpy(buff, data.data(), data.length());
-
- size_t actual;
- size_t count = 0;
- while (count < data.length()) {
- void* xor_buff = xor_sink.GetBuffer(10, &actual);
- ASSERT_EQ(actual, buffsize);
- ASSERT_NE(xor_buff, nullptr);
- memcpy(xor_buff, jumbled.data() + count, buffsize);
- xor_sink.ReturnData(xor_buff, actual);
- count += actual;
- }
-
- std::string answer = reinterpret_cast<char*>(sink.GetPayloadBufPtr());
- ASSERT_EQ(answer, result);
-}
-
TEST(Snapuserd_Test, Snapshot_Metadata) {
CowSnapuserdMetadataTest harness;
harness.Setup();
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
index 5f4d706..978a7f2 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
@@ -347,10 +347,9 @@
*/
bool Snapuserd::ReadMetadata() {
reader_ = std::make_unique<CowReader>();
- CowHeader header;
CowOptions options;
bool metadata_found = false;
- int replace_ops = 0, zero_ops = 0, copy_ops = 0, xor_ops = 0;
+ int replace_ops = 0, zero_ops = 0, copy_ops = 0;
SNAP_LOG(DEBUG) << "ReadMetadata: Parsing cow file";
@@ -359,11 +358,7 @@
return false;
}
- if (!reader_->GetHeader(&header)) {
- SNAP_LOG(ERROR) << "Failed to get header";
- return false;
- }
-
+ const auto& header = reader_->GetHeader();
if (!(header.block_size == BLOCK_SZ)) {
SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size;
return false;
@@ -395,8 +390,8 @@
// this memset will ensure that metadata read is completed.
memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception)));
- while (!cowop_rm_iter->Done()) {
- const CowOperation* cow_op = &cowop_rm_iter->Get();
+ while (!cowop_rm_iter->AtEnd()) {
+ const CowOperation* cow_op = cowop_rm_iter->Get();
struct disk_exception* de =
reinterpret_cast<struct disk_exception*>((char*)de_ptr.get() + offset);
@@ -442,7 +437,7 @@
sizeof(struct disk_exception));
memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception)));
- if (cowop_rm_iter->Done()) {
+ if (cowop_rm_iter->AtEnd()) {
vec_.push_back(std::move(de_ptr));
}
}
@@ -462,9 +457,9 @@
<< " Number of replace/zero ops completed in this area: " << num_ops
<< " Pending copy ops for this area: " << pending_ordered_ops;
- while (!cowop_rm_iter->Done()) {
+ while (!cowop_rm_iter->AtEnd()) {
do {
- const CowOperation* cow_op = &cowop_rm_iter->Get();
+ const CowOperation* cow_op = cowop_rm_iter->Get();
// We have two cases specific cases:
//
@@ -513,15 +508,9 @@
// the merge of operations are done based on the ops present
// in the file.
//===========================================================
- uint64_t block_source = cow_op->source;
- uint64_t block_offset = 0;
- if (cow_op->type == kCowXorOp) {
- block_source /= BLOCK_SZ;
- block_offset = cow_op->source % BLOCK_SZ;
- }
+ 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) ||
- (block_offset > 0 && source_blocks.count(block_source + 1))) {
+ if (dest_blocks.count(cow_op->new_block) || source_blocks.count(block_source)) {
break;
}
}
@@ -529,16 +518,13 @@
pending_ordered_ops -= 1;
vec.push_back(cow_op);
dest_blocks.insert(block_source);
- if (block_offset > 0) {
- dest_blocks.insert(block_source + 1);
- }
source_blocks.insert(cow_op->new_block);
prev_id = cow_op->new_block;
cowop_rm_iter->Next();
- } while (!cowop_rm_iter->Done() && pending_ordered_ops);
+ } while (!cowop_rm_iter->AtEnd() && pending_ordered_ops);
data_chunk_id = GetNextAllocatableChunkId(data_chunk_id);
- SNAP_LOG(DEBUG) << "Batch Merge copy-ops/xor-ops of size: " << vec.size()
+ SNAP_LOG(DEBUG) << "Batch Merge copy-ops of size: " << vec.size()
<< " Area: " << vec_.size() << " Area offset: " << offset
<< " Pending-ordered-ops in this area: " << pending_ordered_ops;
@@ -556,8 +542,6 @@
num_ops += 1;
if (cow_op->type == kCowCopyOp) {
copy_ops++;
- } else { // it->second->type == kCowXorOp
- xor_ops++;
}
if (read_ahead_feature_) {
@@ -580,7 +564,7 @@
sizeof(struct disk_exception));
memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception)));
- if (cowop_rm_iter->Done()) {
+ if (cowop_rm_iter->AtEnd()) {
vec_.push_back(std::move(de_ptr));
SNAP_LOG(DEBUG) << "ReadMetadata() completed; Number of Areas: " << vec_.size();
}
@@ -629,8 +613,8 @@
SNAP_LOG(INFO) << "ReadMetadata completed. Final-chunk-id: " << data_chunk_id
<< " Num Sector: " << ChunkToSector(data_chunk_id)
<< " Replace-ops: " << replace_ops << " Zero-ops: " << zero_ops
- << " Copy-ops: " << copy_ops << " Xor-ops: " << xor_ops
- << " Areas: " << vec_.size() << " Num-ops-merged: " << header.num_merge_ops
+ << " Copy-ops: " << copy_ops << " Areas: " << vec_.size()
+ << " Num-ops-merged: " << header.num_merge_ops
<< " Total-data-ops: " << reader_->get_num_total_data_ops();
// Total number of sectors required for creating dm-user device
@@ -642,11 +626,10 @@
}
bool Snapuserd::MmapMetadata() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
- if (header.major_version >= 2 && header.buffer_size > 0) {
- total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE;
+ if (header.prefix.major_version >= 2 && header.buffer_size > 0) {
+ total_mapped_addr_length_ = header.prefix.header_size + BUFFER_REGION_DEFAULT_SIZE;
read_ahead_feature_ = true;
} else {
// mmap the first 4k page - older COW format
@@ -838,10 +821,9 @@
}
uint64_t Snapuserd::GetBufferMetadataOffset() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
- size_t size = header.header_size + sizeof(BufferState);
+ size_t size = header.prefix.header_size + sizeof(BufferState);
return size;
}
@@ -854,37 +836,33 @@
*
*/
size_t Snapuserd::GetBufferMetadataSize() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
size_t metadata_bytes = (header.buffer_size * sizeof(struct ScratchMetadata)) / BLOCK_SZ;
return metadata_bytes;
}
size_t Snapuserd::GetBufferDataOffset() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
- return (header.header_size + GetBufferMetadataSize());
+ return (header.prefix.header_size + GetBufferMetadataSize());
}
/*
* (2MB - 8K = 2088960 bytes) will be the buffer region to hold the data.
*/
size_t Snapuserd::GetBufferDataSize() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
size_t size = header.buffer_size - GetBufferMetadataSize();
return size;
}
struct BufferState* Snapuserd::GetBufferState() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
struct BufferState* ra_state =
- reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.header_size);
+ reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.prefix.header_size);
return ra_state;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.h b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.h
index 47b9b22..beb6004 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.h
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.h
@@ -170,9 +170,8 @@
// Processing COW operations
bool ProcessCowOp(const CowOperation* cow_op);
bool ProcessReplaceOp(const CowOperation* cow_op);
- // Handles Copy and Xor
+ // Handles Copy
bool ProcessCopyOp(const CowOperation* cow_op);
- bool ProcessXorOp(const CowOperation* cow_op);
bool ProcessZeroOp();
bool ReadFromBaseDevice(const CowOperation* cow_op);
@@ -191,7 +190,6 @@
std::unique_ptr<CowReader> reader_;
BufferSink bufsink_;
- XorSink xorsink_;
std::string cow_device_;
std::string backing_store_device_;
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 c201b23..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,21 +172,12 @@
}
void ReadAheadThread::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;
- }
- if (dest_blocks_.count(cow_op->new_block) || source_blocks_.count(source_block) ||
- (source_offset > 0 && source_blocks_.count(source_block + 1))) {
+ uint64_t source_block = GetCowOpSourceInfoData(cow_op);
+ if (dest_blocks_.count(cow_op->new_block) || source_blocks_.count(source_block)) {
overlap_ = true;
}
dest_blocks_.insert(source_block);
- if (source_offset > 0) {
- dest_blocks_.insert(source_block + 1);
- }
source_blocks_.insert(cow_op->new_block);
}
@@ -200,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;
}
@@ -219,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 0e9f0f1..559dcc7 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
@@ -95,11 +95,17 @@
// internal COW format and if the block is compressed,
// it will be de-compressed.
bool WorkerThread::ProcessReplaceOp(const CowOperation* cow_op) {
- if (!reader_->ReadData(*cow_op, &bufsink_)) {
- SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block;
+ void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
+ if (!buffer) {
+ SNAP_LOG(ERROR) << "No space in buffer sink";
return false;
}
-
+ ssize_t rv = reader_->ReadData(cow_op, buffer, BLOCK_SZ);
+ if (rv != BLOCK_SZ) {
+ SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block
+ << ", return = " << rv;
+ return false;
+ }
return true;
}
@@ -109,20 +115,15 @@
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)) {
- std::string op;
- if (cow_op->type == kCowCopyOp)
- op = "Copy-op";
- else {
- op = "Xor-op";
- }
- SNAP_PLOG(ERROR) << op << " failed. Read from backing store: " << backing_store_device_
+ SNAP_PLOG(ERROR) << "Copy op failed. Read from backing store: " << backing_store_device_
<< "at block :" << offset / BLOCK_SZ << " offset:" << offset % BLOCK_SZ;
return false;
}
@@ -158,23 +159,6 @@
return true;
}
-bool WorkerThread::ProcessXorOp(const CowOperation* cow_op) {
- if (!GetReadAheadPopulatedBuffer(cow_op)) {
- SNAP_LOG(DEBUG) << " GetReadAheadPopulatedBuffer failed..."
- << " new_block: " << cow_op->new_block;
- if (!ReadFromBaseDevice(cow_op)) {
- return false;
- }
- }
- xorsink_.Reset();
- if (!reader_->ReadData(*cow_op, &xorsink_)) {
- SNAP_LOG(ERROR) << "ProcessXorOp failed for block " << cow_op->new_block;
- return false;
- }
-
- return true;
-}
-
bool WorkerThread::ProcessZeroOp() {
// Zero out the entire block
void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
@@ -206,12 +190,8 @@
return ProcessCopyOp(cow_op);
}
- case kCowXorOp: {
- return ProcessXorOp(cow_op);
- }
-
default: {
- SNAP_LOG(ERROR) << "Unknown operation-type found: " << cow_op->type;
+ SNAP_LOG(ERROR) << "Unsupported operation-type found: " << cow_op->type;
}
}
return false;
@@ -529,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
@@ -830,7 +810,6 @@
bool WorkerThread::RunThread() {
InitializeBufsink();
- xorsink_.Initialize(&bufsink_, BLOCK_SZ);
if (!InitializeFds()) {
return false;
diff --git a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_buffer.h b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_buffer.h
index 2e4cac6..a6b6a7f 100644
--- a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_buffer.h
+++ b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_buffer.h
@@ -25,16 +25,15 @@
namespace android {
namespace snapshot {
-class BufferSink : public IByteSink {
+class BufferSink final {
public:
void Initialize(size_t size);
void* GetBufPtr() { return buffer_.get(); }
void Clear() { memset(GetBufPtr(), 0, buffer_size_); }
void* GetPayloadBuffer(size_t size);
- void* GetBuffer(size_t requested, size_t* actual) override;
+ void* GetBuffer(size_t requested, size_t* actual);
void UpdateBufferOffset(size_t size) { buffer_offset_ += size; }
struct dm_user_header* GetHeaderPtr();
- bool ReturnData(void*, size_t) override { return true; }
void ResetBufferOffset() { buffer_offset_ = 0; }
void* GetPayloadBufPtr();
@@ -44,12 +43,12 @@
size_t buffer_size_;
};
-class XorSink : public IByteSink {
+class XorSink final {
public:
void Initialize(BufferSink* sink, size_t size);
void Reset();
- void* GetBuffer(size_t requested, size_t* actual) override;
- bool ReturnData(void* buffer, size_t len) override;
+ void* GetBuffer(size_t requested, size_t* actual);
+ bool ReturnData(void* buffer, size_t len);
private:
BufferSink* bufsink_;
diff --git a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
index 4b62b20..010beb3 100644
--- a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
@@ -32,6 +32,7 @@
static constexpr char kSnapuserdSocket[] = "snapuserd";
static constexpr char kSnapuserdSocketProxy[] = "snapuserd_proxy";
+static constexpr char kDaemonAliveIndicator[] = "daemon-alive-indicator";
// Ensure that the second-stage daemon for snapuserd is running.
bool EnsureSnapuserdStarted();
@@ -44,9 +45,13 @@
std::string Receivemsg();
bool ValidateConnection();
+ std::string GetDaemonAliveIndicatorPath();
+
+ void WaitForServiceToTerminate(std::chrono::milliseconds timeout_ms);
public:
explicit SnapuserdClient(android::base::unique_fd&& sockfd);
+ SnapuserdClient(){};
static std::unique_ptr<SnapuserdClient> Connect(const std::string& socket_name,
std::chrono::milliseconds timeout_ms);
@@ -91,6 +96,17 @@
// Check the update verification status - invoked by update_verifier during
// boot
bool QueryUpdateVerification();
+
+ // Check if Snapuser daemon is ready post selinux transition after OTA boot
+ // This is invoked only by init as there is no sockets setup yet during
+ // selinux transition
+ bool IsTransitionedDaemonReady();
+
+ // Remove the daemon-alive-indicator path post snapshot merge
+ bool RemoveTransitionedDaemonIndicator();
+
+ // Notify init that snapuserd daemon is ready post selinux transition
+ void NotifyTransitionDaemonIsReady();
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h
index c592257..46952c4 100644
--- a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h
+++ b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_kernel.h
@@ -41,6 +41,9 @@
*/
static constexpr uint32_t SECTOR_SHIFT = 9;
+static constexpr size_t BLOCK_SZ = 4096;
+static constexpr size_t BLOCK_SHIFT = (__builtin_ffs(BLOCK_SZ) - 1);
+
typedef __u64 sector_t;
typedef sector_t chunk_t;
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp
index e08cf9b..3bed3a4 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp
@@ -29,10 +29,12 @@
#include <chrono>
#include <sstream>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <fs_mgr/file_wait.h>
#include <snapuserd/snapuserd_client.h>
namespace android {
@@ -92,6 +94,21 @@
return client;
}
+void SnapuserdClient::WaitForServiceToTerminate(std::chrono::milliseconds timeout_ms) {
+ auto start = std::chrono::steady_clock::now();
+ while (android::base::GetProperty("init.svc.snapuserd", "") == "running") {
+ auto now = std::chrono::steady_clock::now();
+ auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
+ if (elapsed >= timeout_ms) {
+ LOG(ERROR) << "Timed out - Snapuserd service did not stop - Forcefully terminating the "
+ "service";
+ android::base::SetProperty("ctl.stop", "snapuserd");
+ return;
+ }
+ std::this_thread::sleep_for(100ms);
+ }
+}
+
bool SnapuserdClient::ValidateConnection() {
if (!Sendmsg("query")) {
return false;
@@ -236,6 +253,8 @@
LOG(ERROR) << "Failed to detach snapuserd.";
return false;
}
+
+ WaitForServiceToTerminate(3s);
return true;
}
@@ -279,5 +298,42 @@
return response == "success";
}
+std::string SnapuserdClient::GetDaemonAliveIndicatorPath() {
+ return "/metadata/ota/" + std::string(kDaemonAliveIndicator);
+}
+
+bool SnapuserdClient::IsTransitionedDaemonReady() {
+ if (!android::fs_mgr::WaitForFile(GetDaemonAliveIndicatorPath(), 10s)) {
+ LOG(ERROR) << "Timed out waiting for daemon indicator path: "
+ << GetDaemonAliveIndicatorPath();
+ return false;
+ }
+
+ return true;
+}
+
+bool SnapuserdClient::RemoveTransitionedDaemonIndicator() {
+ std::string error;
+ std::string filePath = GetDaemonAliveIndicatorPath();
+ if (!android::base::RemoveFileIfExists(filePath, &error)) {
+ LOG(ERROR) << "Failed to remove DaemonAliveIndicatorPath - error: " << error;
+ return false;
+ }
+
+ if (!android::fs_mgr::WaitForFileDeleted(filePath, 5s)) {
+ LOG(ERROR) << "Timed out waiting for " << filePath << " to unlink";
+ return false;
+ }
+
+ return true;
+}
+
+void SnapuserdClient::NotifyTransitionDaemonIsReady() {
+ if (!android::base::WriteStringToFile("1", GetDaemonAliveIndicatorPath())) {
+ PLOG(ERROR) << "Unable to write daemon alive indicator path: "
+ << GetDaemonAliveIndicatorPath();
+ }
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index 2f7775c..36dad33 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -110,15 +110,21 @@
for (int i = arg_start; i < argc; i++) {
auto parts = android::base::Split(argv[i], ",");
if (parts.size() != 4) {
- LOG(ERROR) << "Malformed message, expected three sub-arguments.";
+ LOG(ERROR) << "Malformed message, expected four sub-arguments.";
return false;
}
auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3]);
- if (!handler || !user_server_.StartHandler(handler)) {
+ if (!handler || !user_server_.StartHandler(parts[0])) {
return false;
}
}
+ // We reach this point only during selinux transition during device boot.
+ // At this point, all threads are spin up and are ready to serve the I/O
+ // requests for dm-user. Lets inform init.
+ auto client = std::make_unique<SnapuserdClient>();
+ client->NotifyTransitionDaemonIsReady();
+
// Skip the accept() call to avoid spurious log spam. The server will still
// run until all handlers have completed.
return user_server_.WaitForSocket();
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
new file mode 100644
index 0000000..bdba5c0
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -0,0 +1,374 @@
+// 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 "handler_manager.h"
+
+#include <sys/eventfd.h>
+
+#include <android-base/logging.h>
+
+#include "snapuserd_core.h"
+
+namespace android {
+namespace snapshot {
+
+static constexpr uint8_t kMaxMergeThreads = 2;
+
+HandlerThread::HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd)
+ : snapuserd_(snapuserd), misc_name_(snapuserd_->GetMiscName()) {}
+
+void HandlerThread::FreeResources() {
+ // Each worker thread holds a reference to snapuserd.
+ // Clear them so that all the resources
+ // held by snapuserd is released
+ if (snapuserd_) {
+ snapuserd_->FreeResources();
+ snapuserd_ = nullptr;
+ }
+}
+
+SnapshotHandlerManager::SnapshotHandlerManager() {
+ monitor_merge_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
+ if (monitor_merge_event_fd_ == -1) {
+ PLOG(FATAL) << "monitor_merge_event_fd_: failed to create eventfd";
+ }
+}
+
+std::shared_ptr<HandlerThread> SnapshotHandlerManager::AddHandler(
+ const std::string& misc_name, const std::string& cow_device_path,
+ const std::string& backing_device, const std::string& base_path_merge,
+ int num_worker_threads, bool use_iouring, bool perform_verification) {
+ auto snapuserd = std::make_shared<SnapshotHandler>(misc_name, cow_device_path, backing_device,
+ base_path_merge, num_worker_threads,
+ use_iouring, perform_verification);
+ if (!snapuserd->InitCowDevice()) {
+ LOG(ERROR) << "Failed to initialize Snapuserd";
+ return nullptr;
+ }
+
+ if (!snapuserd->InitializeWorkers()) {
+ LOG(ERROR) << "Failed to initialize workers";
+ return nullptr;
+ }
+
+ auto handler = std::make_shared<HandlerThread>(snapuserd);
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ if (FindHandler(&lock, misc_name) != dm_users_.end()) {
+ LOG(ERROR) << "Handler already exists: " << misc_name;
+ return nullptr;
+ }
+ dm_users_.push_back(handler);
+ }
+ return handler;
+}
+
+bool SnapshotHandlerManager::StartHandler(const std::string& misc_name) {
+ std::lock_guard<std::mutex> lock(lock_);
+ auto iter = FindHandler(&lock, misc_name);
+ if (iter == dm_users_.end()) {
+ LOG(ERROR) << "Could not find handler: " << misc_name;
+ return false;
+ }
+ if (!(*iter)->snapuserd() || (*iter)->snapuserd()->IsAttached()) {
+ LOG(ERROR) << "Tried to re-attach control device: " << misc_name;
+ return false;
+ }
+ if (!StartHandler(*iter)) {
+ return false;
+ }
+ return true;
+}
+
+bool SnapshotHandlerManager::StartHandler(const std::shared_ptr<HandlerThread>& handler) {
+ if (handler->snapuserd()->IsAttached()) {
+ LOG(ERROR) << "Handler already attached";
+ return false;
+ }
+
+ handler->snapuserd()->AttachControlDevice();
+
+ handler->thread() = std::thread(std::bind(&SnapshotHandlerManager::RunThread, this, handler));
+ return true;
+}
+
+bool SnapshotHandlerManager::DeleteHandler(const std::string& misc_name) {
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ auto iter = FindHandler(&lock, misc_name);
+ if (iter == dm_users_.end()) {
+ // After merge is completed, we swap dm-user table with
+ // the underlying dm-linear base device. Hence, worker
+ // threads would have terminted and was removed from
+ // the list.
+ LOG(DEBUG) << "Could not find handler: " << misc_name;
+ return true;
+ }
+
+ if (!(*iter)->ThreadTerminated()) {
+ (*iter)->snapuserd()->NotifyIOTerminated();
+ }
+ }
+ if (!RemoveAndJoinHandler(misc_name)) {
+ return false;
+ }
+ return true;
+}
+
+void SnapshotHandlerManager::RunThread(std::shared_ptr<HandlerThread> handler) {
+ LOG(INFO) << "Entering thread for handler: " << handler->misc_name();
+
+ if (!handler->snapuserd()->Start()) {
+ LOG(ERROR) << " Failed to launch all worker threads";
+ }
+
+ handler->snapuserd()->CloseFds();
+ bool merge_completed = handler->snapuserd()->CheckMergeCompletionStatus();
+ handler->snapuserd()->UnmapBufferRegion();
+
+ auto misc_name = handler->misc_name();
+ LOG(INFO) << "Handler thread about to exit: " << misc_name;
+
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ if (merge_completed) {
+ num_partitions_merge_complete_ += 1;
+ active_merge_threads_ -= 1;
+ WakeupMonitorMergeThread();
+ }
+ handler->SetThreadTerminated();
+ auto iter = FindHandler(&lock, handler->misc_name());
+ if (iter == dm_users_.end()) {
+ // RemoveAndJoinHandler() already removed us from the list, and is
+ // now waiting on a join(), so just return. Additionally, release
+ // all the resources held by snapuserd object which are shared
+ // by worker threads. This should be done when the last reference
+ // of "handler" is released; but we will explicitly release here
+ // to make sure snapuserd object is freed as it is the biggest
+ // consumer of memory in the daemon.
+ handler->FreeResources();
+ LOG(INFO) << "Exiting handler thread to allow for join: " << misc_name;
+ return;
+ }
+
+ LOG(INFO) << "Exiting handler thread and freeing resources: " << misc_name;
+
+ if (handler->snapuserd()->IsAttached()) {
+ handler->thread().detach();
+ }
+
+ // Important: free resources within the lock. This ensures that if
+ // WaitForDelete() is called, the handler is either in the list, or
+ // it's not and its resources are guaranteed to be freed.
+ handler->FreeResources();
+ dm_users_.erase(iter);
+ }
+}
+
+bool SnapshotHandlerManager::InitiateMerge(const std::string& misc_name) {
+ std::lock_guard<std::mutex> lock(lock_);
+ auto iter = FindHandler(&lock, misc_name);
+ if (iter == dm_users_.end()) {
+ LOG(ERROR) << "Could not find handler: " << misc_name;
+ return false;
+ }
+
+ return StartMerge(&lock, *iter);
+}
+
+bool SnapshotHandlerManager::StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
+ const std::shared_ptr<HandlerThread>& handler) {
+ CHECK(proof_of_lock);
+
+ if (!handler->snapuserd()->IsAttached()) {
+ LOG(ERROR) << "Handler not attached to dm-user - Merge thread cannot be started";
+ return false;
+ }
+
+ handler->snapuserd()->MonitorMerge();
+
+ if (!is_merge_monitor_started_) {
+ std::thread(&SnapshotHandlerManager::MonitorMerge, this).detach();
+ is_merge_monitor_started_ = true;
+ }
+
+ merge_handlers_.push(handler);
+ WakeupMonitorMergeThread();
+ return true;
+}
+
+void SnapshotHandlerManager::WakeupMonitorMergeThread() {
+ uint64_t notify = 1;
+ ssize_t rc = TEMP_FAILURE_RETRY(write(monitor_merge_event_fd_.get(), ¬ify, sizeof(notify)));
+ if (rc < 0) {
+ PLOG(FATAL) << "failed to notify monitor merge thread";
+ }
+}
+
+void SnapshotHandlerManager::MonitorMerge() {
+ while (!stop_monitor_merge_thread_) {
+ uint64_t testVal;
+ ssize_t ret =
+ TEMP_FAILURE_RETRY(read(monitor_merge_event_fd_.get(), &testVal, sizeof(testVal)));
+ if (ret == -1) {
+ PLOG(FATAL) << "Failed to read from eventfd";
+ } else if (ret == 0) {
+ LOG(FATAL) << "Hit EOF on eventfd";
+ }
+
+ LOG(INFO) << "MonitorMerge: active-merge-threads: " << active_merge_threads_;
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ while (active_merge_threads_ < kMaxMergeThreads && merge_handlers_.size() > 0) {
+ auto handler = merge_handlers_.front();
+ merge_handlers_.pop();
+
+ if (!handler->snapuserd()) {
+ LOG(INFO) << "MonitorMerge: skipping deleted handler: " << handler->misc_name();
+ continue;
+ }
+
+ LOG(INFO) << "Starting merge for partition: "
+ << handler->snapuserd()->GetMiscName();
+ handler->snapuserd()->InitiateMerge();
+ active_merge_threads_ += 1;
+ }
+ }
+ }
+
+ LOG(INFO) << "Exiting MonitorMerge: size: " << merge_handlers_.size();
+}
+
+std::string SnapshotHandlerManager::GetMergeStatus(const std::string& misc_name) {
+ std::lock_guard<std::mutex> lock(lock_);
+ auto iter = FindHandler(&lock, misc_name);
+ if (iter == dm_users_.end()) {
+ LOG(ERROR) << "Could not find handler: " << misc_name;
+ return {};
+ }
+
+ return (*iter)->snapuserd()->GetMergeStatus();
+}
+
+double SnapshotHandlerManager::GetMergePercentage() {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ double percentage = 0.0;
+ int n = 0;
+
+ for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
+ auto& th = (*iter)->thread();
+ if (th.joinable()) {
+ // Merge percentage by individual partitions wherein merge is still
+ // in-progress
+ percentage += (*iter)->snapuserd()->GetMergePercentage();
+ n += 1;
+ }
+ }
+
+ // Calculate final merge including those partitions where merge was already
+ // completed - num_partitions_merge_complete_ will track them when each
+ // thread exists in RunThread.
+ int total_partitions = n + num_partitions_merge_complete_;
+
+ if (total_partitions) {
+ percentage = ((num_partitions_merge_complete_ * 100.0) + percentage) / total_partitions;
+ }
+
+ LOG(DEBUG) << "Merge %: " << percentage
+ << " num_partitions_merge_complete_: " << num_partitions_merge_complete_
+ << " total_partitions: " << total_partitions << " n: " << n;
+ return percentage;
+}
+
+bool SnapshotHandlerManager::GetVerificationStatus() {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ bool status = true;
+ for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
+ auto& th = (*iter)->thread();
+ if (th.joinable() && status) {
+ status = (*iter)->snapuserd()->CheckPartitionVerification() && status;
+ } else {
+ // return immediately if there is a failure
+ return false;
+ }
+ }
+
+ return status;
+}
+
+bool SnapshotHandlerManager::RemoveAndJoinHandler(const std::string& misc_name) {
+ std::shared_ptr<HandlerThread> handler;
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ auto iter = FindHandler(&lock, misc_name);
+ if (iter == dm_users_.end()) {
+ // Client already deleted.
+ return true;
+ }
+ handler = std::move(*iter);
+ dm_users_.erase(iter);
+ }
+
+ auto& th = handler->thread();
+ if (th.joinable()) {
+ th.join();
+ }
+ return true;
+}
+
+void SnapshotHandlerManager::TerminateMergeThreads() {
+ std::lock_guard<std::mutex> guard(lock_);
+
+ for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
+ if (!(*iter)->ThreadTerminated()) {
+ (*iter)->snapuserd()->NotifyIOTerminated();
+ }
+ }
+}
+
+void SnapshotHandlerManager::JoinAllThreads() {
+ // Acquire the thread list within the lock.
+ std::vector<std::shared_ptr<HandlerThread>> dm_users;
+ {
+ std::lock_guard<std::mutex> guard(lock_);
+ dm_users = std::move(dm_users_);
+ }
+
+ for (auto& client : dm_users) {
+ auto& th = client->thread();
+
+ if (th.joinable()) th.join();
+ }
+
+ stop_monitor_merge_thread_ = true;
+ WakeupMonitorMergeThread();
+}
+
+auto SnapshotHandlerManager::FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
+ const std::string& misc_name) -> HandlerList::iterator {
+ CHECK(proof_of_lock);
+
+ for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
+ if ((*iter)->misc_name() == misc_name) {
+ return iter;
+ }
+ }
+ return dm_users_.end();
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
new file mode 100644
index 0000000..b7ddac1
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
@@ -0,0 +1,131 @@
+// 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 <memory>
+#include <queue>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace snapshot {
+
+class SnapshotHandler;
+
+class HandlerThread {
+ public:
+ explicit HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd);
+
+ void FreeResources();
+ const std::shared_ptr<SnapshotHandler>& snapuserd() const { return snapuserd_; }
+ std::thread& thread() { return thread_; }
+
+ const std::string& misc_name() const { return misc_name_; }
+ bool ThreadTerminated() { return thread_terminated_; }
+ void SetThreadTerminated() { thread_terminated_ = true; }
+
+ private:
+ std::thread thread_;
+ std::shared_ptr<SnapshotHandler> snapuserd_;
+ std::string misc_name_;
+ bool thread_terminated_ = false;
+};
+
+class ISnapshotHandlerManager {
+ public:
+ virtual ~ISnapshotHandlerManager() {}
+
+ // Add a new snapshot handler but do not start serving requests yet.
+ virtual std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge,
+ int num_worker_threads, bool use_iouring,
+ bool perform_verification) = 0;
+
+ // Start serving requests on a snapshot handler.
+ virtual bool StartHandler(const std::string& misc_name) = 0;
+
+ // Stop serving requests on a snapshot handler and remove it.
+ virtual bool DeleteHandler(const std::string& misc_name) = 0;
+
+ // Begin merging blocks on the given snapshot handler.
+ virtual bool InitiateMerge(const std::string& misc_name) = 0;
+
+ // Return a string containing a status code indicating the merge status
+ // on the handler. Returns empty on error.
+ virtual std::string GetMergeStatus(const std::string& misc_name) = 0;
+
+ // Wait until all handlers have terminated.
+ virtual void JoinAllThreads() = 0;
+
+ // Stop any in-progress merge threads.
+ virtual void TerminateMergeThreads() = 0;
+
+ // Returns the merge progress across all merging snapshot handlers.
+ virtual double GetMergePercentage() = 0;
+
+ // Returns whether all snapshots have verified.
+ virtual bool GetVerificationStatus() = 0;
+};
+
+class SnapshotHandlerManager final : public ISnapshotHandlerManager {
+ public:
+ SnapshotHandlerManager();
+ std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge,
+ int num_worker_threads, bool use_iouring,
+ bool perform_verification) override;
+ bool StartHandler(const std::string& misc_name) override;
+ bool DeleteHandler(const std::string& misc_name) override;
+ bool InitiateMerge(const std::string& misc_name) override;
+ std::string GetMergeStatus(const std::string& misc_name) override;
+ void JoinAllThreads() override;
+ void TerminateMergeThreads() override;
+ double GetMergePercentage() override;
+ bool GetVerificationStatus() override;
+
+ private:
+ bool StartHandler(const std::shared_ptr<HandlerThread>& handler);
+ void RunThread(std::shared_ptr<HandlerThread> handler);
+ bool StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
+ const std::shared_ptr<HandlerThread>& handler);
+ void MonitorMerge();
+ void WakeupMonitorMergeThread();
+ bool RemoveAndJoinHandler(const std::string& misc_name);
+
+ // Find a HandlerThread within a lock.
+ using HandlerList = std::vector<std::shared_ptr<HandlerThread>>;
+ HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
+ const std::string& misc_name);
+
+ std::mutex lock_;
+ HandlerList dm_users_;
+
+ bool is_merge_monitor_started_ = false;
+ bool stop_monitor_merge_thread_ = false;
+ int active_merge_threads_ = 0;
+ int num_partitions_merge_complete_ = 0;
+ std::queue<std::shared_ptr<HandlerThread>> merge_handlers_;
+ android::base::unique_fd monitor_merge_event_fd_;
+};
+
+} // 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 492c43f..8e1212b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -31,30 +31,21 @@
using android::base::unique_fd;
SnapshotHandler::SnapshotHandler(std::string misc_name, std::string cow_device,
- std::string backing_device, std::string base_path_merge) {
+ std::string backing_device, std::string base_path_merge,
+ int num_worker_threads, bool use_iouring,
+ bool perform_verification) {
misc_name_ = std::move(misc_name);
cow_device_ = std::move(cow_device);
backing_store_device_ = std::move(backing_device);
control_device_ = "/dev/dm-user/" + misc_name_;
base_path_merge_ = std::move(base_path_merge);
+ num_worker_threads_ = num_worker_threads;
+ is_io_uring_enabled_ = use_iouring;
+ perform_verification_ = perform_verification;
}
bool SnapshotHandler::InitializeWorkers() {
- int num_worker_threads = kNumWorkerThreads;
-
- // We will need multiple worker threads only during
- // device boot after OTA. For all other purposes,
- // one thread is sufficient. We don't want to consume
- // unnecessary memory especially during OTA install phase
- // when daemon will be up during entire post install phase.
- //
- // During boot up, we need multiple threads primarily for
- // update-verification.
- if (is_socket_present_) {
- num_worker_threads = 1;
- }
-
- for (int i = 0; i < num_worker_threads; i++) {
+ 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());
@@ -107,8 +98,7 @@
}
} else {
reader_->UpdateMergeOpsCompleted(num_merge_ops);
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
if (lseek(cow_fd_.get(), 0, SEEK_SET) < 0) {
SNAP_PLOG(ERROR) << "lseek failed";
@@ -163,7 +153,6 @@
bool SnapshotHandler::ReadMetadata() {
reader_ = std::make_unique<CowReader>(CowReader::ReaderFlags::USERSPACE_MERGE, true);
- CowHeader header;
CowOptions options;
SNAP_LOG(DEBUG) << "ReadMetadata: Parsing cow file";
@@ -173,11 +162,7 @@
return false;
}
- if (!reader_->GetHeader(&header)) {
- SNAP_LOG(ERROR) << "Failed to get header";
- return false;
- }
-
+ const auto& header = reader_->GetHeader();
if (!(header.block_size == BLOCK_SZ)) {
SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size;
return false;
@@ -200,8 +185,8 @@
size_t copy_ops = 0, replace_ops = 0, zero_ops = 0, xor_ops = 0;
- while (!cowop_iter->Done()) {
- const CowOperation* cow_op = &cowop_iter->Get();
+ while (!cowop_iter->AtEnd()) {
+ const CowOperation* cow_op = cowop_iter->Get();
if (cow_op->type == kCowCopyOp) {
copy_ops += 1;
@@ -253,12 +238,11 @@
}
bool SnapshotHandler::MmapMetadata() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
- total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE;
+ total_mapped_addr_length_ = header.prefix.header_size + BUFFER_REGION_DEFAULT_SIZE;
- if (header.major_version >= 2 && header.buffer_size > 0) {
+ if (header.prefix.major_version >= 2 && header.buffer_size > 0) {
scratch_space_ = true;
}
@@ -331,19 +315,11 @@
std::async(std::launch::async, &Worker::RunThread, worker_threads_[i].get()));
}
- bool partition_verification = true;
-
- // We don't want to read the blocks during first stage init or
- // during post-install phase.
- if (android::base::EndsWith(misc_name_, "-init") || is_socket_present_) {
- partition_verification = false;
- }
-
std::future<bool> merge_thread =
std::async(std::launch::async, &Worker::RunMergeThread, merge_thread_.get());
// Now that the worker threads are up, scan the partitions.
- if (partition_verification) {
+ if (perform_verification_) {
update_verify_->VerifyUpdatePartition();
}
@@ -384,10 +360,9 @@
}
uint64_t SnapshotHandler::GetBufferMetadataOffset() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
- return (header.header_size + sizeof(BufferState));
+ return (header.prefix.header_size + sizeof(BufferState));
}
/*
@@ -400,8 +375,7 @@
*
*/
size_t SnapshotHandler::GetBufferMetadataSize() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
size_t buffer_size = header.buffer_size;
// If there is no scratch space, then just use the
@@ -414,18 +388,16 @@
}
size_t SnapshotHandler::GetBufferDataOffset() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
- return (header.header_size + GetBufferMetadataSize());
+ return (header.prefix.header_size + GetBufferMetadataSize());
}
/*
* (2MB - 8K = 2088960 bytes) will be the buffer region to hold the data.
*/
size_t SnapshotHandler::GetBufferDataSize() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
size_t buffer_size = header.buffer_size;
// If there is no scratch space, then just use the
@@ -438,11 +410,10 @@
}
struct BufferState* SnapshotHandler::GetBufferState() {
- CowHeader header;
- reader_->GetHeader(&header);
+ const auto& header = reader_->GetHeader();
struct BufferState* ra_state =
- reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.header_size);
+ reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.prefix.header_size);
return ra_state;
}
@@ -450,11 +421,6 @@
struct utsname uts;
unsigned int major, minor;
- if (android::base::GetBoolProperty("snapuserd.test.io_uring.force_disable", false)) {
- SNAP_LOG(INFO) << "io_uring disabled for testing";
- return false;
- }
-
if ((uname(&uts) != 0) || (sscanf(uts.release, "%u.%u", &major, &minor) != 2)) {
SNAP_LOG(ERROR) << "Could not parse the kernel version from uname. "
<< " io_uring not supported";
@@ -482,5 +448,9 @@
return android::base::GetBoolProperty("ro.virtual_ab.io_uring.enabled", false);
}
+bool SnapshotHandler::CheckPartitionVerification() {
+ return update_verify_->CheckPartitionVerification();
+}
+
} // 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 42237ef..c16ad24 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -46,6 +46,8 @@
#include <snapuserd/snapuserd_buffer.h>
#include <snapuserd/snapuserd_kernel.h>
#include <storage_literals/storage_literals.h>
+#include "snapuserd_readahead.h"
+#include "snapuserd_verify.h"
namespace android {
namespace snapshot {
@@ -96,112 +98,6 @@
: merge_state_(state), num_ios_in_progress(n_ios) {}
};
-class ReadAhead {
- public:
- ReadAhead(const std::string& cow_device, const std::string& backing_device,
- const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd);
- bool RunThread();
-
- private:
- void InitializeRAIter();
- bool RAIterDone();
- void RAIterNext();
- void RAResetIter(uint64_t num_blocks);
- const CowOperation* GetRAOpIter();
-
- void InitializeBuffer();
- bool InitReader();
- bool InitializeFds();
-
- void CloseFds() { backing_store_fd_ = {}; }
-
- bool ReadAheadIOStart();
- int PrepareNextReadAhead(uint64_t* source_offset, int* pending_ops,
- std::vector<uint64_t>& blocks,
- std::vector<const CowOperation*>& xor_op_vec);
- bool ReconstructDataFromCow();
- void CheckOverlap(const CowOperation* cow_op);
-
- bool ReadAheadAsyncIO();
- bool ReapIoCompletions(int pending_ios_to_complete);
- bool ReadXorData(size_t block_index, size_t xor_op_index,
- std::vector<const CowOperation*>& xor_op_vec);
- void ProcessXorData(size_t& block_xor_index, size_t& xor_index,
- std::vector<const CowOperation*>& xor_op_vec, void* buffer,
- loff_t& buffer_offset);
- void UpdateScratchMetadata();
-
- bool ReadAheadSyncIO();
- bool InitializeIouring();
- void FinalizeIouring();
-
- void* read_ahead_buffer_;
- void* metadata_buffer_;
-
- std::unique_ptr<ICowOpIter> cowop_iter_;
-
- std::string cow_device_;
- std::string backing_store_device_;
- std::string misc_name_;
-
- unique_fd cow_fd_;
- unique_fd backing_store_fd_;
-
- std::shared_ptr<SnapshotHandler> snapuserd_;
- std::unique_ptr<CowReader> reader_;
-
- std::unordered_set<uint64_t> dest_blocks_;
- std::unordered_set<uint64_t> source_blocks_;
- bool overlap_;
- std::vector<uint64_t> blocks_;
- int total_blocks_merged_ = 0;
- std::unique_ptr<uint8_t[]> ra_temp_buffer_;
- std::unique_ptr<uint8_t[]> ra_temp_meta_buffer_;
- BufferSink bufsink_;
-
- uint64_t total_ra_blocks_completed_ = 0;
- bool read_ahead_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_;
-};
-
-class UpdateVerify {
- public:
- UpdateVerify(const std::string& misc_name);
- void VerifyUpdatePartition();
- bool CheckPartitionVerification();
-
- private:
- enum class UpdateVerifyState {
- VERIFY_UNKNOWN,
- VERIFY_FAILED,
- VERIFY_SUCCESS,
- };
-
- std::string misc_name_;
- UpdateVerifyState state_;
- std::mutex m_lock_;
- std::condition_variable m_cv_;
-
- int kMinThreadsToVerify = 1;
- int kMaxThreadsToVerify = 4;
- uint64_t kThresholdSize = 512_MiB;
- uint64_t kBlockSizeVerify = 1_MiB;
-
- bool IsBlockAligned(uint64_t read_size) { return ((read_size & (BLOCK_SZ - 1)) == 0); }
- void UpdatePartitionVerificationState(UpdateVerifyState state);
- bool VerifyPartition(const std::string& partition_name, const std::string& dm_block_device);
- bool VerifyBlocks(const std::string& partition_name, const std::string& dm_block_device,
- off_t offset, int skip_blocks, uint64_t dev_sz);
-};
-
class Worker {
public:
Worker(const std::string& cow_device, const std::string& backing_device,
@@ -301,7 +197,8 @@
class SnapshotHandler : public std::enable_shared_from_this<SnapshotHandler> {
public:
SnapshotHandler(std::string misc_name, std::string cow_device, std::string backing_device,
- std::string base_path_merge);
+ std::string base_path_merge, int num_workers, bool use_iouring,
+ bool perform_verification);
bool InitCowDevice();
bool Start();
@@ -369,8 +266,6 @@
// Total number of blocks to be merged in a given read-ahead buffer region
void SetMergedBlockCountForNextCommit(int x) { total_ra_blocks_merged_ = x; }
int GetTotalBlocksToMerge() { return total_ra_blocks_merged_; }
- void SetSocketPresent(bool socket) { is_socket_present_ = socket; }
- void SetIouringEnabled(bool io_uring_enabled) { is_io_uring_enabled_ = io_uring_enabled; }
bool MergeInitiated() { return merge_initiated_; }
bool MergeMonitored() { return merge_monitored_; }
double GetMergePercentage() { return merge_completion_percentage_; }
@@ -384,7 +279,7 @@
MERGE_GROUP_STATE ProcessMergingBlock(uint64_t new_block, void* buffer);
bool IsIouringSupported();
- bool CheckPartitionVerification() { return update_verify_->CheckPartitionVerification(); }
+ bool CheckPartitionVerification();
private:
bool ReadMetadata();
@@ -441,9 +336,10 @@
bool merge_initiated_ = false;
bool merge_monitored_ = false;
bool attached_ = false;
- bool is_socket_present_;
bool is_io_uring_enabled_ = false;
bool scratch_space_ = false;
+ int num_worker_threads_ = kNumWorkerThreads;
+ bool perform_verification_ = true;
std::unique_ptr<struct io_uring> ring_;
std::unique_ptr<UpdateVerify> update_verify_;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
index 0d0f711..44b7319 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
@@ -76,11 +76,15 @@
// internal COW format and if the block is compressed,
// it will be de-compressed.
bool Worker::ProcessReplaceOp(const CowOperation* cow_op) {
- if (!reader_->ReadData(*cow_op, &bufsink_)) {
+ void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
+ if (!buffer) {
+ SNAP_LOG(ERROR) << "ProcessReplaceOp failed to allocate buffer";
+ return false;
+ }
+ if (!reader_->ReadData(cow_op, buffer, BLOCK_SZ)) {
SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block;
return false;
}
-
return true;
}
@@ -90,12 +94,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) << "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)
@@ -125,12 +130,26 @@
if (!ReadFromSourceDevice(cow_op)) {
return false;
}
+
xorsink_.Reset();
- if (!reader_->ReadData(*cow_op, &xorsink_)) {
- SNAP_LOG(ERROR) << "ProcessXorOp failed for block " << cow_op->new_block;
+
+ size_t actual = 0;
+ void* buffer = xorsink_.GetBuffer(BLOCK_SZ, &actual);
+ if (!buffer || actual < BLOCK_SZ) {
+ SNAP_LOG(ERROR) << "ProcessXorOp failed to get buffer of " << BLOCK_SZ << " size, got "
+ << actual;
return false;
}
-
+ ssize_t size = reader_->ReadData(cow_op, buffer, BLOCK_SZ);
+ if (size != BLOCK_SZ) {
+ SNAP_LOG(ERROR) << "ProcessXorOp failed for block " << cow_op->new_block
+ << ", return value: " << size;
+ return false;
+ }
+ if (!xorsink_.ReturnData(buffer, size)) {
+ SNAP_LOG(ERROR) << "ProcessXorOp failed to return data";
+ return false;
+ }
return true;
}
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 d57f434..ce95b76 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_merge.cpp
@@ -30,8 +30,8 @@
bool checkOrderedOp = (replace_zero_vec == nullptr);
do {
- if (!cowop_iter_->Done() && num_ops) {
- const CowOperation* cow_op = &cowop_iter_->Get();
+ if (!cowop_iter_->AtEnd() && num_ops) {
+ const CowOperation* cow_op = cowop_iter_->Get();
if (checkOrderedOp && !IsOrderedOp(*cow_op)) {
break;
}
@@ -45,8 +45,8 @@
num_ops -= 1;
nr_consecutive = 1;
- while (!cowop_iter_->Done() && num_ops) {
- const CowOperation* op = &cowop_iter_->Get();
+ while (!cowop_iter_->AtEnd() && num_ops) {
+ const CowOperation* op = cowop_iter_->Get();
if (checkOrderedOp && !IsOrderedOp(*op)) {
break;
}
@@ -85,7 +85,7 @@
SNAP_LOG(INFO) << "MergeReplaceZeroOps started....";
- while (!cowop_iter_->Done()) {
+ while (!cowop_iter_->AtEnd()) {
int num_ops = PAYLOAD_BUFFER_SZ / BLOCK_SZ;
std::vector<const CowOperation*> replace_zero_vec;
uint64_t source_offset;
@@ -93,7 +93,7 @@
int linear_blocks = PrepareMerge(&source_offset, &num_ops, &replace_zero_vec);
if (linear_blocks == 0) {
// Merge complete
- CHECK(cowop_iter_->Done());
+ CHECK(cowop_iter_->AtEnd());
break;
}
@@ -180,8 +180,8 @@
SNAP_LOG(INFO) << "MergeOrderedOpsAsync started....";
- while (!cowop_iter_->Done()) {
- const CowOperation* cow_op = &cowop_iter_->Get();
+ while (!cowop_iter_->AtEnd()) {
+ const CowOperation* cow_op = cowop_iter_->Get();
if (!IsOrderedOp(*cow_op)) {
break;
}
@@ -361,8 +361,8 @@
SNAP_LOG(INFO) << "MergeOrderedOps started....";
- while (!cowop_iter_->Done()) {
- const CowOperation* cow_op = &cowop_iter_->Get();
+ while (!cowop_iter_->AtEnd()) {
+ const CowOperation* cow_op = cowop_iter_->Get();
if (!IsOrderedOp(*cow_op)) {
break;
}
@@ -443,7 +443,7 @@
if (!MergeOrderedOpsAsync()) {
SNAP_LOG(ERROR) << "MergeOrderedOpsAsync failed - Falling back to synchronous I/O";
// Reset the iter so that we retry the merge
- while (blocks_merged_in_group_ && !cowop_iter_->RDone()) {
+ while (blocks_merged_in_group_ && !cowop_iter_->AtBegin()) {
cowop_iter_->Prev();
blocks_merged_in_group_ -= 1;
}
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 fbe57d2..399f7b8 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "snapuserd_readahead.h"
+
#include "snapuserd_core.h"
namespace android {
@@ -32,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;
}
@@ -64,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);
}
@@ -86,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
@@ -114,6 +120,24 @@
return nr_consecutive;
}
+class [[nodiscard]] AutoNotifyReadAheadFailed {
+ public:
+ AutoNotifyReadAheadFailed(std::shared_ptr<SnapshotHandler> snapuserd) : snapuserd_(snapuserd) {}
+
+ ~AutoNotifyReadAheadFailed() {
+ if (cancelled_) {
+ return;
+ }
+ snapuserd_->ReadAheadIOFailed();
+ }
+
+ void Cancel() { cancelled_ = true; }
+
+ private:
+ std::shared_ptr<SnapshotHandler> snapuserd_;
+ bool cancelled_ = false;
+};
+
bool ReadAhead::ReconstructDataFromCow() {
std::unordered_map<uint64_t, void*>& read_ahead_buffer_map = snapuserd_->GetReadAheadMap();
loff_t metadata_offset = 0;
@@ -145,6 +169,8 @@
metadata_offset += sizeof(struct ScratchMetadata);
}
+ AutoNotifyReadAheadFailed notify_read_ahead_failed(snapuserd_);
+
// We are done re-constructing the mapping; however, we need to make sure
// all the COW operations to-be merged are present in the re-constructed
// mapping.
@@ -162,7 +188,6 @@
if (!(num_ops == 0)) {
SNAP_LOG(ERROR) << "ReconstructDataFromCow failed. Not all ops recoverd "
<< " Pending ops: " << num_ops;
- snapuserd_->ReadAheadIOFailed();
return false;
}
@@ -175,11 +200,11 @@
if (!snapuserd_->ReadAheadIOCompleted(true)) {
SNAP_LOG(ERROR) << "ReadAheadIOCompleted failed...";
- snapuserd_->ReadAheadIOFailed();
return false;
}
SNAP_LOG(INFO) << "ReconstructDataFromCow success";
+ notify_read_ahead_failed.Cancel();
return true;
}
@@ -467,9 +492,16 @@
if (xor_op_index < xor_op_vec.size()) {
const CowOperation* xor_op = xor_op_vec[xor_op_index];
if (xor_op->new_block == new_block) {
- if (!reader_->ReadData(*xor_op, &bufsink_)) {
+ void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
+ if (!buffer) {
+ SNAP_LOG(ERROR) << "ReadAhead - failed to allocate buffer for block: "
+ << xor_op->new_block;
+ return false;
+ }
+ if (ssize_t rv = reader_->ReadData(xor_op, buffer, BLOCK_SZ); rv != BLOCK_SZ) {
SNAP_LOG(ERROR)
- << " ReadAhead - XorOp Read failed for block: " << xor_op->new_block;
+ << " ReadAhead - XorOp Read failed for block: " << xor_op->new_block
+ << ", return value: " << rv;
return false;
}
@@ -492,6 +524,8 @@
blocks_.clear();
std::vector<const CowOperation*> xor_op_vec;
+ AutoNotifyReadAheadFailed notify_read_ahead_failed(snapuserd_);
+
bufsink_.ResetBufferOffset();
// Number of ops to be merged in this window. This is a fixed size
@@ -518,8 +552,6 @@
<< " offset :" << source_offset % BLOCK_SZ
<< " buffer_offset : " << buffer_offset << " io_size : " << io_size
<< " buf-addr : " << read_ahead_buffer_;
-
- snapuserd_->ReadAheadIOFailed();
return false;
}
@@ -530,6 +562,7 @@
// Done with merging ordered ops
if (RAIterDone() && total_blocks_merged_ == 0) {
+ notify_read_ahead_failed.Cancel();
return true;
}
@@ -560,20 +593,25 @@
// Check if this block is an XOR op
if (xor_op->new_block == new_block) {
// Read the xor'ed data from COW
- if (!reader_->ReadData(*xor_op, &bufsink)) {
+ void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
+ if (!buffer) {
+ SNAP_LOG(ERROR) << "ReadAhead - failed to allocate buffer";
+ return false;
+ }
+ if (ssize_t rv = reader_->ReadData(xor_op, buffer, BLOCK_SZ); rv != BLOCK_SZ) {
SNAP_LOG(ERROR)
- << " ReadAhead - XorOp Read failed for block: " << xor_op->new_block;
- snapuserd_->ReadAheadIOFailed();
+ << " ReadAhead - XorOp Read failed for block: " << xor_op->new_block
+ << ", return value: " << rv;
return false;
}
// Pointer to the data read from base device
- uint8_t* buffer = reinterpret_cast<uint8_t*>(bufptr);
+ uint8_t* read_buffer = reinterpret_cast<uint8_t*>(bufptr);
// Get the xor'ed data read from COW device
uint8_t* xor_data = reinterpret_cast<uint8_t*>(bufsink.GetPayloadBufPtr());
// Retrieve the original data
for (size_t byte_offset = 0; byte_offset < BLOCK_SZ; byte_offset++) {
- buffer[byte_offset] ^= xor_data[byte_offset];
+ read_buffer[byte_offset] ^= xor_data[byte_offset];
}
// Move to next XOR op
@@ -604,6 +642,7 @@
bm->new_block = 0;
bm->file_offset = 0;
+ notify_read_ahead_failed.Cancel();
return true;
}
@@ -768,6 +807,7 @@
if (!reader_->InitForMerge(std::move(cow_fd_))) {
return false;
}
+ header_ = reader_->GetHeader();
return true;
}
@@ -776,7 +816,7 @@
}
bool ReadAhead::RAIterDone() {
- if (cowop_iter_->Done()) {
+ if (cowop_iter_->AtEnd()) {
return true;
}
@@ -794,15 +834,14 @@
}
void ReadAhead::RAResetIter(uint64_t num_blocks) {
- while (num_blocks && !cowop_iter_->RDone()) {
+ while (num_blocks && !cowop_iter_->AtBegin()) {
cowop_iter_->Prev();
num_blocks -= 1;
}
}
const CowOperation* ReadAhead::GetRAOpIter() {
- const CowOperation* cow_op = &cowop_iter_->Get();
- return cow_op;
+ return cowop_iter_->Get();
}
void ReadAhead::InitializeBuffer() {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
new file mode 100644
index 0000000..d3ba126
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
@@ -0,0 +1,113 @@
+// 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 <stdint.h>
+
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+#include <libsnapshot/cow_reader.h>
+#include <liburing.h>
+#include <snapuserd/snapuserd_buffer.h>
+
+namespace android {
+namespace snapshot {
+
+class SnapshotHandler;
+
+class ReadAhead {
+ public:
+ ReadAhead(const std::string& cow_device, const std::string& backing_device,
+ const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd);
+ bool RunThread();
+
+ private:
+ void InitializeRAIter();
+ bool RAIterDone();
+ void RAIterNext();
+ void RAResetIter(uint64_t num_blocks);
+ const CowOperation* GetRAOpIter();
+
+ void InitializeBuffer();
+ bool InitReader();
+ bool InitializeFds();
+
+ void CloseFds() { backing_store_fd_ = {}; }
+
+ bool ReadAheadIOStart();
+ int PrepareNextReadAhead(uint64_t* source_offset, int* pending_ops,
+ std::vector<uint64_t>& blocks,
+ std::vector<const CowOperation*>& xor_op_vec);
+ bool ReconstructDataFromCow();
+ void CheckOverlap(const CowOperation* cow_op);
+
+ bool ReadAheadAsyncIO();
+ bool ReapIoCompletions(int pending_ios_to_complete);
+ bool ReadXorData(size_t block_index, size_t xor_op_index,
+ std::vector<const CowOperation*>& xor_op_vec);
+ void ProcessXorData(size_t& block_xor_index, size_t& xor_index,
+ std::vector<const CowOperation*>& xor_op_vec, void* buffer,
+ loff_t& buffer_offset);
+ void UpdateScratchMetadata();
+
+ bool ReadAheadSyncIO();
+ bool InitializeIouring();
+ void FinalizeIouring();
+
+ void* read_ahead_buffer_;
+ void* metadata_buffer_;
+
+ std::unique_ptr<ICowOpIter> cowop_iter_;
+
+ std::string cow_device_;
+ std::string backing_store_device_;
+ std::string misc_name_;
+
+ android::base::unique_fd cow_fd_;
+ android::base::unique_fd backing_store_fd_;
+
+ 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_;
+ bool overlap_;
+ std::vector<uint64_t> blocks_;
+ int total_blocks_merged_ = 0;
+ std::unique_ptr<uint8_t[]> ra_temp_buffer_;
+ std::unique_ptr<uint8_t[]> ra_temp_meta_buffer_;
+ BufferSink bufsink_;
+
+ uint64_t total_ra_blocks_completed_ = 0;
+ bool read_ahead_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_;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index d437d32..c953f1a 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -29,6 +29,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
+#include <android-base/strings.h>
#include <fs_mgr/file_wait.h>
#include <snapuserd/snapuserd_client.h>
#include "snapuserd_server.h"
@@ -44,28 +45,9 @@
using android::base::borrowed_fd;
using android::base::unique_fd;
-DaemonOps UserSnapshotServer::Resolveop(std::string& input) {
- if (input == "init") return DaemonOps::INIT;
- if (input == "start") return DaemonOps::START;
- if (input == "stop") return DaemonOps::STOP;
- if (input == "query") return DaemonOps::QUERY;
- if (input == "delete") return DaemonOps::DELETE;
- if (input == "detach") return DaemonOps::DETACH;
- if (input == "supports") return DaemonOps::SUPPORTS;
- if (input == "initiate_merge") return DaemonOps::INITIATE;
- if (input == "merge_percent") return DaemonOps::PERCENTAGE;
- if (input == "getstatus") return DaemonOps::GETSTATUS;
- if (input == "update-verify") return DaemonOps::UPDATE_VERIFY;
-
- return DaemonOps::INVALID;
-}
-
UserSnapshotServer::UserSnapshotServer() {
- monitor_merge_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
- if (monitor_merge_event_fd_ == -1) {
- PLOG(FATAL) << "monitor_merge_event_fd_: failed to create eventfd";
- }
terminating_ = false;
+ handlers_ = std::make_unique<SnapshotHandlerManager>();
}
UserSnapshotServer::~UserSnapshotServer() {
@@ -98,12 +80,9 @@
void UserSnapshotServer::ShutdownThreads() {
terminating_ = true;
- JoinAllThreads();
+ handlers_->JoinAllThreads();
}
-UserSnapshotDmUserHandler::UserSnapshotDmUserHandler(std::shared_ptr<SnapshotHandler> snapuserd)
- : snapuserd_(snapuserd), misc_name_(snapuserd_->GetMiscName()) {}
-
bool UserSnapshotServer::Sendmsg(android::base::borrowed_fd fd, const std::string& msg) {
ssize_t ret = TEMP_FAILURE_RETRY(send(fd.get(), msg.data(), msg.size(), MSG_NOSIGNAL));
if (ret < 0) {
@@ -134,226 +113,118 @@
std::vector<std::string> out;
Parsemsg(str, delim, out);
- DaemonOps op = Resolveop(out[0]);
- switch (op) {
- case DaemonOps::INIT: {
- // Message format:
- // init,<misc_name>,<cow_device_path>,<backing_device>,<base_path_merge>
- //
- // Reads the metadata and send the number of sectors
- if (out.size() != 5) {
- LOG(ERROR) << "Malformed init message, " << out.size() << " parts";
- return Sendmsg(fd, "fail");
- }
-
- auto handler = AddHandler(out[1], out[2], out[3], out[4]);
- if (!handler) {
- return Sendmsg(fd, "fail");
- }
-
- auto retval = "success," + std::to_string(handler->snapuserd()->GetNumSectors());
- return Sendmsg(fd, retval);
- }
- case DaemonOps::START: {
- // Message format:
- // start,<misc_name>
- //
- // Start the new thread which binds to dm-user misc device
- if (out.size() != 2) {
- LOG(ERROR) << "Malformed start message, " << out.size() << " parts";
- return Sendmsg(fd, "fail");
- }
-
- std::lock_guard<std::mutex> lock(lock_);
- auto iter = FindHandler(&lock, out[1]);
- if (iter == dm_users_.end()) {
- LOG(ERROR) << "Could not find handler: " << out[1];
- return Sendmsg(fd, "fail");
- }
- if (!(*iter)->snapuserd() || (*iter)->snapuserd()->IsAttached()) {
- LOG(ERROR) << "Tried to re-attach control device: " << out[1];
- return Sendmsg(fd, "fail");
- }
- if (!StartHandler(*iter)) {
- return Sendmsg(fd, "fail");
- }
- return Sendmsg(fd, "success");
- }
- case DaemonOps::STOP: {
- // Message format: stop
- //
- // Stop all the threads gracefully and then shutdown the
- // main thread
- SetTerminating();
- ShutdownThreads();
- return true;
- }
- case DaemonOps::QUERY: {
- // Message format: query
- //
- // As part of transition, Second stage daemon will be
- // created before terminating the first stage daemon. Hence,
- // for a brief period client may have to distiguish between
- // first stage daemon and second stage daemon.
- //
- // Second stage daemon is marked as active and hence will
- // be ready to receive control message.
- return Sendmsg(fd, GetDaemonStatus());
- }
- case DaemonOps::DELETE: {
- // Message format:
- // delete,<misc_name>
- if (out.size() != 2) {
- LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
- return Sendmsg(fd, "fail");
- }
- {
- std::lock_guard<std::mutex> lock(lock_);
- auto iter = FindHandler(&lock, out[1]);
- if (iter == dm_users_.end()) {
- // After merge is completed, we swap dm-user table with
- // the underlying dm-linear base device. Hence, worker
- // threads would have terminted and was removed from
- // the list.
- LOG(DEBUG) << "Could not find handler: " << out[1];
- return Sendmsg(fd, "success");
- }
-
- if (!(*iter)->ThreadTerminated()) {
- (*iter)->snapuserd()->NotifyIOTerminated();
- }
- }
- if (!RemoveAndJoinHandler(out[1])) {
- return Sendmsg(fd, "fail");
- }
- return Sendmsg(fd, "success");
- }
- case DaemonOps::DETACH: {
- std::lock_guard<std::mutex> lock(lock_);
- TerminateMergeThreads(&lock);
- terminating_ = true;
- return true;
- }
- case DaemonOps::SUPPORTS: {
- if (out.size() != 2) {
- LOG(ERROR) << "Malformed supports message, " << out.size() << " parts";
- return Sendmsg(fd, "fail");
- }
- if (out[1] == "second_stage_socket_handoff") {
- return Sendmsg(fd, "success");
- }
+ const auto& cmd = out[0];
+ if (cmd == "init") {
+ // Message format:
+ // init,<misc_name>,<cow_device_path>,<backing_device>,<base_path_merge>
+ //
+ // Reads the metadata and send the number of sectors
+ if (out.size() != 5) {
+ LOG(ERROR) << "Malformed init message, " << out.size() << " parts";
return Sendmsg(fd, "fail");
}
- case DaemonOps::INITIATE: {
- if (out.size() != 2) {
- LOG(ERROR) << "Malformed initiate-merge message, " << out.size() << " parts";
- return Sendmsg(fd, "fail");
- }
- if (out[0] == "initiate_merge") {
- std::lock_guard<std::mutex> lock(lock_);
- auto iter = FindHandler(&lock, out[1]);
- if (iter == dm_users_.end()) {
- LOG(ERROR) << "Could not find handler: " << out[1];
- return Sendmsg(fd, "fail");
- }
- if (!StartMerge(&lock, *iter)) {
- return Sendmsg(fd, "fail");
- }
-
- return Sendmsg(fd, "success");
- }
+ auto handler = AddHandler(out[1], out[2], out[3], out[4]);
+ if (!handler) {
return Sendmsg(fd, "fail");
}
- case DaemonOps::PERCENTAGE: {
- std::lock_guard<std::mutex> lock(lock_);
- double percentage = GetMergePercentage(&lock);
- return Sendmsg(fd, std::to_string(percentage));
+ auto retval = "success," + std::to_string(handler->snapuserd()->GetNumSectors());
+ return Sendmsg(fd, retval);
+ } else if (cmd == "start") {
+ // Message format:
+ // start,<misc_name>
+ //
+ // Start the new thread which binds to dm-user misc device
+ if (out.size() != 2) {
+ LOG(ERROR) << "Malformed start message, " << out.size() << " parts";
+ return Sendmsg(fd, "fail");
}
- case DaemonOps::GETSTATUS: {
- // Message format:
- // getstatus,<misc_name>
- if (out.size() != 2) {
- LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
- return Sendmsg(fd, "snapshot-merge-failed");
- }
- {
- std::lock_guard<std::mutex> lock(lock_);
- auto iter = FindHandler(&lock, out[1]);
- if (iter == dm_users_.end()) {
- LOG(ERROR) << "Could not find handler: " << out[1];
- return Sendmsg(fd, "snapshot-merge-failed");
- }
- std::string merge_status = GetMergeStatus(*iter);
- return Sendmsg(fd, merge_status);
- }
+ if (!handlers_->StartHandler(out[1])) {
+ return Sendmsg(fd, "fail");
}
- case DaemonOps::UPDATE_VERIFY: {
- std::lock_guard<std::mutex> lock(lock_);
- if (!UpdateVerification(&lock)) {
- return Sendmsg(fd, "fail");
- }
-
+ return Sendmsg(fd, "success");
+ } else if (cmd == "stop") {
+ // Message format: stop
+ //
+ // Stop all the threads gracefully and then shutdown the
+ // main thread
+ SetTerminating();
+ ShutdownThreads();
+ return true;
+ } else if (cmd == "query") {
+ // Message format: query
+ //
+ // As part of transition, Second stage daemon will be
+ // created before terminating the first stage daemon. Hence,
+ // for a brief period client may have to distiguish between
+ // first stage daemon and second stage daemon.
+ //
+ // Second stage daemon is marked as active and hence will
+ // be ready to receive control message.
+ return Sendmsg(fd, GetDaemonStatus());
+ } else if (cmd == "delete") {
+ // Message format:
+ // delete,<misc_name>
+ if (out.size() != 2) {
+ LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
+ return Sendmsg(fd, "fail");
+ }
+ if (!handlers_->DeleteHandler(out[1])) {
+ return Sendmsg(fd, "fail");
+ }
+ return Sendmsg(fd, "success");
+ } else if (cmd == "detach") {
+ handlers_->TerminateMergeThreads();
+ terminating_ = true;
+ return true;
+ } else if (cmd == "supports") {
+ if (out.size() != 2) {
+ LOG(ERROR) << "Malformed supports message, " << out.size() << " parts";
+ return Sendmsg(fd, "fail");
+ }
+ if (out[1] == "second_stage_socket_handoff") {
return Sendmsg(fd, "success");
}
- default: {
- LOG(ERROR) << "Received unknown message type from client";
- Sendmsg(fd, "fail");
- return false;
+ return Sendmsg(fd, "fail");
+ } else if (cmd == "initiate_merge") {
+ if (out.size() != 2) {
+ LOG(ERROR) << "Malformed initiate-merge message, " << out.size() << " parts";
+ return Sendmsg(fd, "fail");
}
- }
-}
-
-void UserSnapshotServer::RunThread(std::shared_ptr<UserSnapshotDmUserHandler> handler) {
- LOG(INFO) << "Entering thread for handler: " << handler->misc_name();
-
- if (!handler->snapuserd()->Start()) {
- LOG(ERROR) << " Failed to launch all worker threads";
- }
-
- handler->snapuserd()->CloseFds();
- bool merge_completed = handler->snapuserd()->CheckMergeCompletionStatus();
- handler->snapuserd()->UnmapBufferRegion();
-
- auto misc_name = handler->misc_name();
- LOG(INFO) << "Handler thread about to exit: " << misc_name;
-
- {
- std::lock_guard<std::mutex> lock(lock_);
- if (merge_completed) {
- num_partitions_merge_complete_ += 1;
- active_merge_threads_ -= 1;
- WakeupMonitorMergeThread();
+ if (out[0] == "initiate_merge") {
+ if (!handlers_->InitiateMerge(out[1])) {
+ return Sendmsg(fd, "fail");
+ }
+ return Sendmsg(fd, "success");
}
- handler->SetThreadTerminated();
- auto iter = FindHandler(&lock, handler->misc_name());
- if (iter == dm_users_.end()) {
- // RemoveAndJoinHandler() already removed us from the list, and is
- // now waiting on a join(), so just return. Additionally, release
- // all the resources held by snapuserd object which are shared
- // by worker threads. This should be done when the last reference
- // of "handler" is released; but we will explicitly release here
- // to make sure snapuserd object is freed as it is the biggest
- // consumer of memory in the daemon.
- handler->FreeResources();
- LOG(INFO) << "Exiting handler thread to allow for join: " << misc_name;
- return;
+ return Sendmsg(fd, "fail");
+ } else if (cmd == "merge_percent") {
+ double percentage = handlers_->GetMergePercentage();
+ return Sendmsg(fd, std::to_string(percentage));
+ } else if (cmd == "getstatus") {
+ // Message format:
+ // getstatus,<misc_name>
+ if (out.size() != 2) {
+ LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
+ return Sendmsg(fd, "snapshot-merge-failed");
}
-
- LOG(INFO) << "Exiting handler thread and freeing resources: " << misc_name;
-
- if (handler->snapuserd()->IsAttached()) {
- handler->thread().detach();
+ auto status = handlers_->GetMergeStatus(out[1]);
+ if (status.empty()) {
+ return Sendmsg(fd, "snapshot-merge-failed");
}
-
- // Important: free resources within the lock. This ensures that if
- // WaitForDelete() is called, the handler is either in the list, or
- // it's not and its resources are guaranteed to be freed.
- handler->FreeResources();
- dm_users_.erase(iter);
+ return Sendmsg(fd, status);
+ } else if (cmd == "update-verify") {
+ if (!handlers_->GetVerificationStatus()) {
+ return Sendmsg(fd, "fail");
+ }
+ return Sendmsg(fd, "success");
+ } else {
+ LOG(ERROR) << "Received unknown message type from client";
+ Sendmsg(fd, "fail");
+ return false;
}
}
@@ -422,28 +293,10 @@
}
}
- JoinAllThreads();
+ handlers_->JoinAllThreads();
return true;
}
-void UserSnapshotServer::JoinAllThreads() {
- // Acquire the thread list within the lock.
- std::vector<std::shared_ptr<UserSnapshotDmUserHandler>> dm_users;
- {
- std::lock_guard<std::mutex> guard(lock_);
- dm_users = std::move(dm_users_);
- }
-
- for (auto& client : dm_users) {
- auto& th = client->thread();
-
- if (th.joinable()) th.join();
- }
-
- stop_monitor_merge_thread_ = true;
- WakeupMonitorMergeThread();
-}
-
void UserSnapshotServer::AddWatchedFd(android::base::borrowed_fd fd, int events) {
struct pollfd p = {};
p.fd = fd.get();
@@ -483,191 +336,35 @@
SetTerminating();
}
-std::shared_ptr<UserSnapshotDmUserHandler> UserSnapshotServer::AddHandler(
- const std::string& misc_name, const std::string& cow_device_path,
- const std::string& backing_device, const std::string& base_path_merge) {
- auto snapuserd = std::make_shared<SnapshotHandler>(misc_name, cow_device_path, backing_device,
- base_path_merge);
- if (!snapuserd->InitCowDevice()) {
- LOG(ERROR) << "Failed to initialize Snapuserd";
- return nullptr;
+std::shared_ptr<HandlerThread> UserSnapshotServer::AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge) {
+ // We will need multiple worker threads only during
+ // device boot after OTA. For all other purposes,
+ // one thread is sufficient. We don't want to consume
+ // unnecessary memory especially during OTA install phase
+ // when daemon will be up during entire post install phase.
+ //
+ // During boot up, we need multiple threads primarily for
+ // update-verification.
+ int num_worker_threads = kNumWorkerThreads;
+ if (is_socket_present_) {
+ num_worker_threads = 1;
}
- snapuserd->SetSocketPresent(is_socket_present_);
- snapuserd->SetIouringEnabled(io_uring_enabled_);
-
- if (!snapuserd->InitializeWorkers()) {
- LOG(ERROR) << "Failed to initialize workers";
- return nullptr;
+ bool perform_verification = true;
+ if (android::base::EndsWith(misc_name, "-init") || is_socket_present_) {
+ perform_verification = false;
}
- auto handler = std::make_shared<UserSnapshotDmUserHandler>(snapuserd);
- {
- std::lock_guard<std::mutex> lock(lock_);
- if (FindHandler(&lock, misc_name) != dm_users_.end()) {
- LOG(ERROR) << "Handler already exists: " << misc_name;
- return nullptr;
- }
- dm_users_.push_back(handler);
- }
- return handler;
-}
-
-bool UserSnapshotServer::StartHandler(const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
- if (handler->snapuserd()->IsAttached()) {
- LOG(ERROR) << "Handler already attached";
- return false;
- }
-
- handler->snapuserd()->AttachControlDevice();
-
- handler->thread() = std::thread(std::bind(&UserSnapshotServer::RunThread, this, handler));
- return true;
-}
-
-bool UserSnapshotServer::StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
- const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
- CHECK(proof_of_lock);
-
- if (!handler->snapuserd()->IsAttached()) {
- LOG(ERROR) << "Handler not attached to dm-user - Merge thread cannot be started";
- return false;
- }
-
- handler->snapuserd()->MonitorMerge();
-
- if (!is_merge_monitor_started_.has_value()) {
- std::thread(&UserSnapshotServer::MonitorMerge, this).detach();
- is_merge_monitor_started_ = true;
- }
-
- merge_handlers_.push(handler);
- WakeupMonitorMergeThread();
- return true;
-}
-
-auto UserSnapshotServer::FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
- const std::string& misc_name) -> HandlerList::iterator {
- CHECK(proof_of_lock);
-
- for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
- if ((*iter)->misc_name() == misc_name) {
- return iter;
- }
- }
- return dm_users_.end();
-}
-
-void UserSnapshotServer::TerminateMergeThreads(std::lock_guard<std::mutex>* proof_of_lock) {
- CHECK(proof_of_lock);
-
- for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
- if (!(*iter)->ThreadTerminated()) {
- (*iter)->snapuserd()->NotifyIOTerminated();
- }
- }
-}
-
-std::string UserSnapshotServer::GetMergeStatus(
- const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
- return handler->snapuserd()->GetMergeStatus();
-}
-
-double UserSnapshotServer::GetMergePercentage(std::lock_guard<std::mutex>* proof_of_lock) {
- CHECK(proof_of_lock);
- double percentage = 0.0;
- int n = 0;
-
- for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
- auto& th = (*iter)->thread();
- if (th.joinable()) {
- // Merge percentage by individual partitions wherein merge is still
- // in-progress
- percentage += (*iter)->snapuserd()->GetMergePercentage();
- n += 1;
- }
- }
-
- // Calculate final merge including those partitions where merge was already
- // completed - num_partitions_merge_complete_ will track them when each
- // thread exists in RunThread.
- int total_partitions = n + num_partitions_merge_complete_;
-
- if (total_partitions) {
- percentage = ((num_partitions_merge_complete_ * 100.0) + percentage) / total_partitions;
- }
-
- LOG(DEBUG) << "Merge %: " << percentage
- << " num_partitions_merge_complete_: " << num_partitions_merge_complete_
- << " total_partitions: " << total_partitions << " n: " << n;
- return percentage;
-}
-
-bool UserSnapshotServer::RemoveAndJoinHandler(const std::string& misc_name) {
- std::shared_ptr<UserSnapshotDmUserHandler> handler;
- {
- std::lock_guard<std::mutex> lock(lock_);
-
- auto iter = FindHandler(&lock, misc_name);
- if (iter == dm_users_.end()) {
- // Client already deleted.
- return true;
- }
- handler = std::move(*iter);
- dm_users_.erase(iter);
- }
-
- auto& th = handler->thread();
- if (th.joinable()) {
- th.join();
- }
- return true;
-}
-
-void UserSnapshotServer::WakeupMonitorMergeThread() {
- uint64_t notify = 1;
- ssize_t rc = TEMP_FAILURE_RETRY(write(monitor_merge_event_fd_.get(), ¬ify, sizeof(notify)));
- if (rc < 0) {
- PLOG(FATAL) << "failed to notify monitor merge thread";
- }
-}
-
-void UserSnapshotServer::MonitorMerge() {
- while (!stop_monitor_merge_thread_) {
- uint64_t testVal;
- ssize_t ret =
- TEMP_FAILURE_RETRY(read(monitor_merge_event_fd_.get(), &testVal, sizeof(testVal)));
- if (ret == -1) {
- PLOG(FATAL) << "Failed to read from eventfd";
- } else if (ret == 0) {
- LOG(FATAL) << "Hit EOF on eventfd";
- }
-
- LOG(INFO) << "MonitorMerge: active-merge-threads: " << active_merge_threads_;
- {
- std::lock_guard<std::mutex> lock(lock_);
- while (active_merge_threads_ < kMaxMergeThreads && merge_handlers_.size() > 0) {
- auto handler = merge_handlers_.front();
- merge_handlers_.pop();
-
- if (!handler->snapuserd()) {
- LOG(INFO) << "MonitorMerge: skipping deleted handler: " << handler->misc_name();
- continue;
- }
-
- LOG(INFO) << "Starting merge for partition: "
- << handler->snapuserd()->GetMiscName();
- handler->snapuserd()->InitiateMerge();
- active_merge_threads_ += 1;
- }
- }
- }
-
- LOG(INFO) << "Exiting MonitorMerge: size: " << merge_handlers_.size();
+ return handlers_->AddHandler(misc_name, cow_device_path, backing_device, base_path_merge,
+ num_worker_threads, io_uring_enabled_, perform_verification);
}
bool UserSnapshotServer::WaitForSocket() {
- auto scope_guard = android::base::make_scope_guard([this]() -> void { JoinAllThreads(); });
+ auto scope_guard =
+ android::base::make_scope_guard([this]() -> void { handlers_->JoinAllThreads(); });
auto socket_path = ANDROID_SOCKET_DIR "/"s + kSnapuserdSocketProxy;
@@ -764,21 +461,8 @@
return true;
}
-bool UserSnapshotServer::UpdateVerification(std::lock_guard<std::mutex>* proof_of_lock) {
- CHECK(proof_of_lock);
-
- bool status = true;
- for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
- auto& th = (*iter)->thread();
- if (th.joinable() && status) {
- status = (*iter)->snapuserd()->CheckPartitionVerification() && status;
- } else {
- // return immediately if there is a failure
- return false;
- }
- }
-
- return status;
+bool UserSnapshotServer::StartHandler(const std::string& misc_name) {
+ return handlers_->StartHandler(misc_name);
}
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
index c2af61f..988c01a 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
@@ -31,6 +31,7 @@
#include <vector>
#include <android-base/unique_fd.h>
+#include "handler_manager.h"
#include "snapuserd_core.h"
namespace android {
@@ -39,48 +40,6 @@
static constexpr uint32_t kMaxPacketSize = 512;
static constexpr uint8_t kMaxMergeThreads = 2;
-enum class DaemonOps {
- INIT,
- START,
- QUERY,
- STOP,
- DELETE,
- DETACH,
- SUPPORTS,
- INITIATE,
- PERCENTAGE,
- GETSTATUS,
- UPDATE_VERIFY,
- INVALID,
-};
-
-class UserSnapshotDmUserHandler {
- public:
- explicit UserSnapshotDmUserHandler(std::shared_ptr<SnapshotHandler> snapuserd);
-
- void FreeResources() {
- // Each worker thread holds a reference to snapuserd.
- // Clear them so that all the resources
- // held by snapuserd is released
- if (snapuserd_) {
- snapuserd_->FreeResources();
- snapuserd_ = nullptr;
- }
- }
- const std::shared_ptr<SnapshotHandler>& snapuserd() const { return snapuserd_; }
- std::thread& thread() { return thread_; }
-
- const std::string& misc_name() const { return misc_name_; }
- bool ThreadTerminated() { return thread_terminated_; }
- void SetThreadTerminated() { thread_terminated_ = true; }
-
- private:
- std::thread thread_;
- std::shared_ptr<SnapshotHandler> snapuserd_;
- std::string misc_name_;
- bool thread_terminated_ = false;
-};
-
class UserSnapshotServer {
private:
android::base::unique_fd sockfd_;
@@ -88,21 +47,12 @@
volatile bool received_socket_signal_ = false;
std::vector<struct pollfd> watched_fds_;
bool is_socket_present_ = false;
- int num_partitions_merge_complete_ = 0;
- int active_merge_threads_ = 0;
- bool stop_monitor_merge_thread_ = false;
bool is_server_running_ = false;
bool io_uring_enabled_ = false;
- std::optional<bool> is_merge_monitor_started_;
-
- android::base::unique_fd monitor_merge_event_fd_;
+ std::unique_ptr<ISnapshotHandlerManager> handlers_;
std::mutex lock_;
- using HandlerList = std::vector<std::shared_ptr<UserSnapshotDmUserHandler>>;
- HandlerList dm_users_;
- std::queue<std::shared_ptr<UserSnapshotDmUserHandler>> merge_handlers_;
-
void AddWatchedFd(android::base::borrowed_fd fd, int events);
void AcceptClient();
bool HandleClient(android::base::borrowed_fd fd, int revents);
@@ -111,28 +61,14 @@
bool Receivemsg(android::base::borrowed_fd fd, const std::string& str);
void ShutdownThreads();
- bool RemoveAndJoinHandler(const std::string& control_device);
- DaemonOps Resolveop(std::string& input);
std::string GetDaemonStatus();
void Parsemsg(std::string const& msg, const char delim, std::vector<std::string>& out);
bool IsTerminating() { return terminating_; }
- void RunThread(std::shared_ptr<UserSnapshotDmUserHandler> handler);
- void MonitorMerge();
-
void JoinAllThreads();
bool StartWithSocket(bool start_listening);
- // Find a UserSnapshotDmUserHandler within a lock.
- HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
- const std::string& misc_name);
-
- double GetMergePercentage(std::lock_guard<std::mutex>* proof_of_lock);
- void TerminateMergeThreads(std::lock_guard<std::mutex>* proof_of_lock);
-
- bool UpdateVerification(std::lock_guard<std::mutex>* proof_of_lock);
-
public:
UserSnapshotServer();
~UserSnapshotServer();
@@ -143,16 +79,12 @@
bool RunForSocketHandoff();
bool WaitForSocket();
- std::shared_ptr<UserSnapshotDmUserHandler> AddHandler(const std::string& misc_name,
- const std::string& cow_device_path,
- const std::string& backing_device,
- const std::string& base_path_merge);
- bool StartHandler(const std::shared_ptr<UserSnapshotDmUserHandler>& handler);
- bool StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
- const std::shared_ptr<UserSnapshotDmUserHandler>& handler);
- std::string GetMergeStatus(const std::shared_ptr<UserSnapshotDmUserHandler>& handler);
+ std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge);
+ bool StartHandler(const std::string& misc_name);
- void WakeupMonitorMergeThread();
void SetTerminating() { terminating_ = true; }
void ReceivedSocketSignal() { received_socket_signal_ = true; }
void SetServerRunning() { is_server_running_ = true; }
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index d670f1e..efe0c14 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -37,9 +37,9 @@
#include <libdm/dm.h>
#include <libdm/loop_control.h>
#include <libsnapshot/cow_writer.h>
-#include <snapuserd/snapuserd_client.h>
#include <storage_literals/storage_literals.h>
+#include "handler_manager.h"
#include "snapuserd_core.h"
DEFINE_string(force_config, "", "Force testing mode with iouring disabled");
@@ -54,8 +54,6 @@
using namespace android::dm;
using namespace std;
-static constexpr char kSnapuserdSocketTest[] = "snapuserdTest";
-
class Tempdevice {
public:
Tempdevice(const std::string& name, const DmTable& table)
@@ -68,15 +66,15 @@
}
~Tempdevice() {
if (valid_) {
- dm_.DeleteDevice(name_);
+ dm_.DeleteDeviceIfExists(name_);
}
}
bool Destroy() {
if (!valid_) {
- return false;
+ return true;
}
valid_ = false;
- return dm_.DeleteDevice(name_);
+ return dm_.DeleteDeviceIfExists(name_);
}
const std::string& path() const { return path_; }
const std::string& name() const { return name_; }
@@ -99,9 +97,9 @@
bool valid_;
};
-class SnapuserTest final {
+class SnapuserdTest : public ::testing::Test {
public:
- bool Setup();
+ bool SetupDefault();
bool SetupOrderedOps();
bool SetupOrderedOpsInverted();
bool SetupCopyOverlap_1();
@@ -118,11 +116,16 @@
static const uint64_t kSectorSize = 512;
+ protected:
+ void SetUp() override {}
+ void TearDown() override { Shutdown(); }
+
private:
void SetupImpl();
void SimulateDaemonRestart();
+ std::unique_ptr<ICowWriter> CreateCowDeviceInternal();
void CreateCowDevice();
void CreateCowDeviceOrderedOps();
void CreateCowDeviceOrderedOpsInverted();
@@ -134,7 +137,6 @@
void SetDeviceControlName();
void InitDaemon();
void CreateDmUserDevice();
- void StartSnapuserdDaemon();
unique_ptr<LoopDevice> base_loop_;
unique_ptr<Tempdevice> dmuser_dev_;
@@ -144,9 +146,9 @@
unique_fd base_fd_;
std::unique_ptr<TemporaryFile> cow_system_;
- std::unique_ptr<SnapuserdClient> client_;
std::unique_ptr<uint8_t[]> orig_buffer_;
std::unique_ptr<uint8_t[]> merged_buffer_;
+ SnapshotHandlerManager handlers_;
bool setup_ok_ = false;
bool merge_ok_ = false;
size_t size_ = 100_MiB;
@@ -172,49 +174,47 @@
return fd;
}
-void SnapuserTest::Shutdown() {
+void SnapuserdTest::Shutdown() {
ASSERT_TRUE(dmuser_dev_->Destroy());
auto misc_device = "/dev/dm-user/" + system_device_ctrl_name_;
- ASSERT_TRUE(client_->WaitForDeviceDelete(system_device_ctrl_name_));
+ ASSERT_TRUE(handlers_.DeleteHandler(system_device_ctrl_name_));
ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted(misc_device, 10s));
- ASSERT_TRUE(client_->DetachSnapuserd());
+ handlers_.TerminateMergeThreads();
}
-bool SnapuserTest::Setup() {
+bool SnapuserdTest::SetupDefault() {
SetupImpl();
return setup_ok_;
}
-bool SnapuserTest::SetupOrderedOps() {
+bool SnapuserdTest::SetupOrderedOps() {
CreateBaseDevice();
CreateCowDeviceOrderedOps();
return SetupDaemon();
}
-bool SnapuserTest::SetupOrderedOpsInverted() {
+bool SnapuserdTest::SetupOrderedOpsInverted() {
CreateBaseDevice();
CreateCowDeviceOrderedOpsInverted();
return SetupDaemon();
}
-bool SnapuserTest::SetupCopyOverlap_1() {
+bool SnapuserdTest::SetupCopyOverlap_1() {
CreateBaseDevice();
CreateCowDeviceWithCopyOverlap_1();
return SetupDaemon();
}
-bool SnapuserTest::SetupCopyOverlap_2() {
+bool SnapuserdTest::SetupCopyOverlap_2() {
CreateBaseDevice();
CreateCowDeviceWithCopyOverlap_2();
return SetupDaemon();
}
-bool SnapuserTest::SetupDaemon() {
+bool SnapuserdTest::SetupDaemon() {
SetDeviceControlName();
- StartSnapuserdDaemon();
-
CreateDmUserDevice();
InitCowDevice();
InitDaemon();
@@ -224,21 +224,7 @@
return setup_ok_;
}
-void SnapuserTest::StartSnapuserdDaemon() {
- pid_t pid = fork();
- ASSERT_GE(pid, 0);
- if (pid == 0) {
- std::string arg0 = "/system/bin/snapuserd";
- std::string arg1 = "-socket="s + kSnapuserdSocketTest;
- char* const argv[] = {arg0.data(), arg1.data(), nullptr};
- ASSERT_GE(execv(arg0.c_str(), argv), 0);
- } else {
- client_ = SnapuserdClient::Connect(kSnapuserdSocketTest, 10s);
- ASSERT_NE(client_, nullptr);
- }
-}
-
-void SnapuserTest::CreateBaseDevice() {
+void SnapuserdTest::CreateBaseDevice() {
unique_fd rnd_fd;
total_base_size_ = (size_ * 5);
@@ -261,7 +247,7 @@
ASSERT_TRUE(base_loop_->valid());
}
-void SnapuserTest::ReadSnapshotDeviceAndValidate() {
+void SnapuserdTest::ReadSnapshotDeviceAndValidate() {
unique_fd fd(open(dmuser_dev_->path().c_str(), O_RDONLY));
ASSERT_GE(fd, 0);
std::unique_ptr<uint8_t[]> snapuserd_buffer = std::make_unique<uint8_t[]>(size_);
@@ -292,23 +278,30 @@
ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 4), size_), 0);
}
-void SnapuserTest::CreateCowDeviceWithCopyOverlap_2() {
+std::unique_ptr<ICowWriter> SnapuserdTest::CreateCowDeviceInternal() {
std::string path = android::base::GetExecutableDirectory();
cow_system_ = std::make_unique<TemporaryFile>(path);
CowOptions options;
options.compression = "gz";
- CowWriter writer(options);
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
+ unique_fd fd(cow_system_->fd);
+ cow_system_->fd = -1;
- size_t num_blocks = size_ / options.block_size;
+ return CreateCowWriter(kDefaultCowVersion, options, std::move(fd));
+}
+
+void SnapuserdTest::CreateCowDeviceWithCopyOverlap_2() {
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
+
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t x = num_blocks;
size_t blk_src_copy = 0;
// Create overlapping copy operations
while (1) {
- ASSERT_TRUE(writer.AddCopy(blk_src_copy, blk_src_copy + 1));
+ ASSERT_TRUE(writer->AddCopy(blk_src_copy, blk_src_copy + 1));
x -= 1;
if (x == 1) {
break;
@@ -317,7 +310,7 @@
}
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
@@ -344,23 +337,17 @@
}
}
-void SnapuserTest::CreateCowDeviceWithCopyOverlap_1() {
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+void SnapuserdTest::CreateCowDeviceWithCopyOverlap_1() {
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t x = num_blocks;
size_t blk_src_copy = num_blocks - 1;
// Create overlapping copy operations
while (1) {
- ASSERT_TRUE(writer.AddCopy(blk_src_copy + 1, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(blk_src_copy + 1, blk_src_copy));
x -= 1;
if (x == 0) {
ASSERT_EQ(blk_src_copy, 0);
@@ -370,7 +357,7 @@
}
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
@@ -380,19 +367,20 @@
true);
// Merged operations
- ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), options.block_size, 0),
+ ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), writer->GetBlockSize(),
+ 0),
true);
ASSERT_EQ(android::base::ReadFullyAtOffset(
- base_fd_, (char*)orig_buffer_.get() + options.block_size, size_, 0),
+ base_fd_, (char*)orig_buffer_.get() + writer->GetBlockSize(), size_, 0),
true);
}
-void SnapuserTest::CreateCowDeviceOrderedOpsInverted() {
+void SnapuserdTest::CreateCowDeviceOrderedOpsInverted() {
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -407,13 +395,7 @@
offset += 1_MiB;
}
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t blk_end_copy = num_blocks * 3;
size_t source_blk = num_blocks - 1;
size_t blk_src_copy = blk_end_copy - 1;
@@ -421,7 +403,7 @@
size_t x = num_blocks;
while (1) {
- ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy));
x -= 1;
if (x == 0) {
break;
@@ -431,12 +413,12 @@
}
for (size_t i = num_blocks; i > 0; i--) {
- ASSERT_TRUE(writer.AddXorBlocks(num_blocks + i - 1,
- &random_buffer_1_.get()[options.block_size * (i - 1)],
- options.block_size, 2 * num_blocks + i - 1, xor_offset));
+ ASSERT_TRUE(writer->AddXorBlocks(
+ num_blocks + i - 1, &random_buffer_1_.get()[writer->GetBlockSize() * (i - 1)],
+ writer->GetBlockSize(), 2 * num_blocks + i - 1, xor_offset));
}
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
// Read the entire base device
@@ -450,12 +432,12 @@
}
}
-void SnapuserTest::CreateCowDeviceOrderedOps() {
+void SnapuserdTest::CreateCowDeviceOrderedOps() {
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -471,20 +453,14 @@
}
memset(random_buffer_1_.get(), 0, size_);
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t x = num_blocks;
size_t source_blk = 0;
size_t blk_src_copy = 2 * num_blocks;
uint16_t xor_offset = 5;
while (1) {
- ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy));
x -= 1;
if (x == 0) {
@@ -494,10 +470,10 @@
blk_src_copy += 1;
}
- ASSERT_TRUE(writer.AddXorBlocks(num_blocks, random_buffer_1_.get(), size_, 2 * num_blocks,
- xor_offset));
+ ASSERT_TRUE(writer->AddXorBlocks(num_blocks, random_buffer_1_.get(), size_, 2 * num_blocks,
+ xor_offset));
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
// Read the entire base device
@@ -511,12 +487,12 @@
}
}
-void SnapuserTest::CreateCowDevice() {
+void SnapuserdTest::CreateCowDevice() {
unique_fd rnd_fd;
loff_t offset = 0;
- std::string path = android::base::GetExecutableDirectory();
- cow_system_ = std::make_unique<TemporaryFile>(path);
+ auto writer = CreateCowDeviceInternal();
+ ASSERT_NE(writer, nullptr);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -531,13 +507,7 @@
offset += 1_MiB;
}
- CowOptions options;
- options.compression = "gz";
- CowWriter writer(options);
-
- ASSERT_TRUE(writer.Initialize(cow_system_->fd));
-
- size_t num_blocks = size_ / options.block_size;
+ size_t num_blocks = size_ / writer->GetBlockSize();
size_t blk_end_copy = num_blocks * 2;
size_t source_blk = num_blocks - 1;
size_t blk_src_copy = blk_end_copy - 1;
@@ -551,11 +521,11 @@
for (int i = 0; i < num_blocks; i++) {
sequence[num_blocks + i] = 5 * num_blocks - 1 - i;
}
- ASSERT_TRUE(writer.AddSequenceData(2 * num_blocks, sequence));
+ ASSERT_TRUE(writer->AddSequenceData(2 * num_blocks, sequence));
size_t x = num_blocks;
while (1) {
- ASSERT_TRUE(writer.AddCopy(source_blk, blk_src_copy));
+ ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy));
x -= 1;
if (x == 0) {
break;
@@ -567,24 +537,24 @@
source_blk = num_blocks;
blk_src_copy = blk_end_copy;
- ASSERT_TRUE(writer.AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
+ ASSERT_TRUE(writer->AddRawBlocks(source_blk, random_buffer_1_.get(), size_));
size_t blk_zero_copy_start = source_blk + num_blocks;
size_t blk_zero_copy_end = blk_zero_copy_start + num_blocks;
- ASSERT_TRUE(writer.AddZeroBlocks(blk_zero_copy_start, num_blocks));
+ ASSERT_TRUE(writer->AddZeroBlocks(blk_zero_copy_start, num_blocks));
size_t blk_random2_replace_start = blk_zero_copy_end;
- ASSERT_TRUE(writer.AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_));
+ ASSERT_TRUE(writer->AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_));
size_t blk_xor_start = blk_random2_replace_start + num_blocks;
size_t xor_offset = BLOCK_SZ / 2;
- ASSERT_TRUE(writer.AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks,
- xor_offset));
+ ASSERT_TRUE(writer->AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks,
+ xor_offset));
// Flush operations
- ASSERT_TRUE(writer.Finalize());
+ ASSERT_TRUE(writer->Finalize());
// Construct the buffer required for validation
orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
std::string zero_buffer(size_, 0);
@@ -601,13 +571,21 @@
}
}
-void SnapuserTest::InitCowDevice() {
- uint64_t num_sectors = client_->InitDmUserCow(system_device_ctrl_name_, cow_system_->path,
- base_loop_->device(), base_loop_->device());
- ASSERT_NE(num_sectors, 0);
+void SnapuserdTest::InitCowDevice() {
+ bool use_iouring = true;
+ if (FLAGS_force_config == "iouring_disabled") {
+ use_iouring = false;
+ }
+
+ auto handler =
+ handlers_.AddHandler(system_device_ctrl_name_, cow_system_->path, base_loop_->device(),
+ base_loop_->device(), 1, use_iouring, false);
+ ASSERT_NE(handler, nullptr);
+ ASSERT_NE(handler->snapuserd(), nullptr);
+ ASSERT_NE(handler->snapuserd()->GetNumSectors(), 0);
}
-void SnapuserTest::SetDeviceControlName() {
+void SnapuserdTest::SetDeviceControlName() {
system_device_name_.clear();
system_device_ctrl_name_.clear();
@@ -619,7 +597,7 @@
system_device_ctrl_name_ = system_device_name_ + "-ctrl";
}
-void SnapuserTest::CreateDmUserDevice() {
+void SnapuserdTest::CreateDmUserDevice() {
unique_fd fd(TEMP_FAILURE_RETRY(open(base_loop_->device().c_str(), O_RDONLY | O_CLOEXEC)));
ASSERT_TRUE(fd > 0);
@@ -641,14 +619,13 @@
ASSERT_TRUE(android::fs_mgr::WaitForFile(misc_device, 10s));
}
-void SnapuserTest::InitDaemon() {
- bool ok = client_->AttachDmUser(system_device_ctrl_name_);
- ASSERT_TRUE(ok);
+void SnapuserdTest::InitDaemon() {
+ ASSERT_TRUE(handlers_.StartHandler(system_device_ctrl_name_));
}
-void SnapuserTest::CheckMergeCompletion() {
+void SnapuserdTest::CheckMergeCompletion() {
while (true) {
- double percentage = client_->GetMergePercent();
+ double percentage = handlers_.GetMergePercentage();
if ((int)percentage == 100) {
break;
}
@@ -657,14 +634,12 @@
}
}
-void SnapuserTest::SetupImpl() {
+void SnapuserdTest::SetupImpl() {
CreateBaseDevice();
CreateCowDevice();
SetDeviceControlName();
- StartSnapuserdDaemon();
-
CreateDmUserDevice();
InitCowDevice();
InitDaemon();
@@ -672,36 +647,34 @@
setup_ok_ = true;
}
-bool SnapuserTest::Merge() {
+bool SnapuserdTest::Merge() {
StartMerge();
CheckMergeCompletion();
merge_ok_ = true;
return merge_ok_;
}
-void SnapuserTest::StartMerge() {
- bool ok = client_->InitiateMerge(system_device_ctrl_name_);
- ASSERT_TRUE(ok);
+void SnapuserdTest::StartMerge() {
+ ASSERT_TRUE(handlers_.InitiateMerge(system_device_ctrl_name_));
}
-void SnapuserTest::ValidateMerge() {
+void SnapuserdTest::ValidateMerge() {
merged_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, merged_buffer_.get(), total_base_size_, 0),
true);
ASSERT_EQ(memcmp(merged_buffer_.get(), orig_buffer_.get(), total_base_size_), 0);
}
-void SnapuserTest::SimulateDaemonRestart() {
+void SnapuserdTest::SimulateDaemonRestart() {
Shutdown();
std::this_thread::sleep_for(500ms);
SetDeviceControlName();
- StartSnapuserdDaemon();
CreateDmUserDevice();
InitCowDevice();
InitDaemon();
}
-void SnapuserTest::MergeInterruptRandomly(int max_duration) {
+void SnapuserdTest::MergeInterruptRandomly(int max_duration) {
std::srand(std::time(nullptr));
StartMerge();
@@ -716,7 +689,7 @@
ASSERT_TRUE(Merge());
}
-void SnapuserTest::MergeInterruptFixed(int duration) {
+void SnapuserdTest::MergeInterruptFixed(int duration) {
StartMerge();
for (int i = 0; i < 25; i++) {
@@ -729,7 +702,7 @@
ASSERT_TRUE(Merge());
}
-void SnapuserTest::MergeInterrupt() {
+void SnapuserdTest::MergeInterrupt() {
// Interrupt merge at various intervals
StartMerge();
std::this_thread::sleep_for(250ms);
@@ -758,104 +731,93 @@
ASSERT_TRUE(Merge());
}
-TEST(Snapuserd_Test, Snapshot_IO_TEST) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.Setup());
+TEST_F(SnapuserdTest, Snapshot_IO_TEST) {
+ ASSERT_TRUE(SetupDefault());
// I/O before merge
- harness.ReadSnapshotDeviceAndValidate();
- ASSERT_TRUE(harness.Merge());
- harness.ValidateMerge();
+ ReadSnapshotDeviceAndValidate();
+ ASSERT_TRUE(Merge());
+ ValidateMerge();
// I/O after merge - daemon should read directly
// from base device
- harness.ReadSnapshotDeviceAndValidate();
- harness.Shutdown();
+ ReadSnapshotDeviceAndValidate();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_MERGE_IO_TEST) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.Setup());
+TEST_F(SnapuserdTest, Snapshot_MERGE_IO_TEST) {
+ ASSERT_TRUE(SetupDefault());
// Issue I/O before merge begins
- std::async(std::launch::async, &SnapuserTest::ReadSnapshotDeviceAndValidate, &harness);
+ std::async(std::launch::async, &SnapuserdTest::ReadSnapshotDeviceAndValidate, this);
// Start the merge
- ASSERT_TRUE(harness.Merge());
- harness.ValidateMerge();
- harness.Shutdown();
+ ASSERT_TRUE(Merge());
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_MERGE_IO_TEST_1) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.Setup());
+TEST_F(SnapuserdTest, Snapshot_MERGE_IO_TEST_1) {
+ ASSERT_TRUE(SetupDefault());
// Start the merge
- harness.StartMerge();
+ StartMerge();
// Issue I/O in parallel when merge is in-progress
- std::async(std::launch::async, &SnapuserTest::ReadSnapshotDeviceAndValidate, &harness);
- harness.CheckMergeCompletion();
- harness.ValidateMerge();
- harness.Shutdown();
+ std::async(std::launch::async, &SnapuserdTest::ReadSnapshotDeviceAndValidate, this);
+ CheckMergeCompletion();
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_Merge_Resume) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.Setup());
- harness.MergeInterrupt();
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_Merge_Resume) {
+ ASSERT_TRUE(SetupDefault());
+ MergeInterrupt();
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_1) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupCopyOverlap_1());
- ASSERT_TRUE(harness.Merge());
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_COPY_Overlap_TEST_1) {
+ ASSERT_TRUE(SetupCopyOverlap_1());
+ ASSERT_TRUE(Merge());
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_2) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupCopyOverlap_2());
- ASSERT_TRUE(harness.Merge());
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_COPY_Overlap_TEST_2) {
+ ASSERT_TRUE(SetupCopyOverlap_2());
+ ASSERT_TRUE(Merge());
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_COPY_Overlap_Merge_Resume_TEST) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupCopyOverlap_1());
- harness.MergeInterrupt();
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_COPY_Overlap_Merge_Resume_TEST) {
+ ASSERT_TRUE(SetupCopyOverlap_1());
+ MergeInterrupt();
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_Merge_Crash_Fixed_Ordered) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupOrderedOps());
- harness.MergeInterruptFixed(300);
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_Merge_Crash_Fixed_Ordered) {
+ ASSERT_TRUE(SetupOrderedOps());
+ MergeInterruptFixed(300);
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_Merge_Crash_Random_Ordered) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupOrderedOps());
- harness.MergeInterruptRandomly(500);
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_Merge_Crash_Random_Ordered) {
+ ASSERT_TRUE(SetupOrderedOps());
+ MergeInterruptRandomly(500);
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_Merge_Crash_Fixed_Inverted) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupOrderedOpsInverted());
- harness.MergeInterruptFixed(50);
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_Merge_Crash_Fixed_Inverted) {
+ ASSERT_TRUE(SetupOrderedOpsInverted());
+ MergeInterruptFixed(50);
+ ValidateMerge();
+ Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_Merge_Crash_Random_Inverted) {
- SnapuserTest harness;
- ASSERT_TRUE(harness.SetupOrderedOpsInverted());
- harness.MergeInterruptRandomly(50);
- harness.ValidateMerge();
- harness.Shutdown();
+TEST_F(SnapuserdTest, Snapshot_Merge_Crash_Random_Inverted) {
+ ASSERT_TRUE(SetupOrderedOpsInverted());
+ MergeInterruptRandomly(50);
+ ValidateMerge();
+ Shutdown();
}
} // namespace snapshot
@@ -866,20 +828,5 @@
gflags::ParseCommandLineFlags(&argc, &argv, false);
- android::base::SetProperty("ctl.stop", "snapuserd");
-
- if (FLAGS_force_config == "iouring_disabled") {
- if (!android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1")) {
- return testing::AssertionFailure()
- << "Failed to disable property: snapuserd.test.io_uring.disabled";
- }
- }
-
- int ret = RUN_ALL_TESTS();
-
- if (FLAGS_force_config == "iouring_disabled") {
- android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
- }
-
- return ret;
+ return RUN_ALL_TESTS();
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp
index 18c1dfc..6817340 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.cpp
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-#include "snapuserd_core.h"
+#include "snapuserd_verify.h"
#include <android-base/chrono_utils.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
+#include "snapuserd_core.h"
+
namespace android {
namespace snapshot {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
new file mode 100644
index 0000000..d07d2f8
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
@@ -0,0 +1,64 @@
+// 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 <stdint.h>
+#include <sys/types.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+
+#include <snapuserd/snapuserd_kernel.h>
+#include <storage_literals/storage_literals.h>
+
+namespace android {
+namespace snapshot {
+
+using namespace android::storage_literals;
+
+class UpdateVerify {
+ public:
+ UpdateVerify(const std::string& misc_name);
+ void VerifyUpdatePartition();
+ bool CheckPartitionVerification();
+
+ private:
+ enum class UpdateVerifyState {
+ VERIFY_UNKNOWN,
+ VERIFY_FAILED,
+ VERIFY_SUCCESS,
+ };
+
+ std::string misc_name_;
+ UpdateVerifyState state_;
+ std::mutex m_lock_;
+ std::condition_variable m_cv_;
+
+ int kMinThreadsToVerify = 1;
+ int kMaxThreadsToVerify = 4;
+ uint64_t kThresholdSize = 512_MiB;
+ uint64_t kBlockSizeVerify = 1_MiB;
+
+ bool IsBlockAligned(uint64_t read_size) { return ((read_size & (BLOCK_SZ - 1)) == 0); }
+ void UpdatePartitionVerificationState(UpdateVerifyState state);
+ bool VerifyPartition(const std::string& partition_name, const std::string& dm_block_device);
+ bool VerifyBlocks(const std::string& partition_name, const std::string& dm_block_device,
+ off_t offset, int skip_blocks, uint64_t dev_sz);
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index b05123a..2eac347 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -130,12 +130,7 @@
return true;
}
-std::string HashSnapshot(ISnapshotWriter* writer) {
- auto reader = writer->OpenReader();
- if (!reader) {
- return {};
- }
-
+std::string HashSnapshot(ICowWriter::FileDescriptor* reader) {
SHA256_CTX ctx;
SHA256_Init(&ctx);
@@ -214,68 +209,6 @@
return partition_update->mutable_new_partition_info()->size();
}
-AssertionResult LowSpaceUserdata::Init(uint64_t max_free_space) {
- auto res = ReadUserdataStats();
- if (!res) return res;
-
- // Try to fill up the disk as much as possible until free_space_ <= max_free_space.
- big_file_ = std::make_unique<TemporaryFile>();
- if (big_file_->fd == -1) {
- return AssertionFailure() << strerror(errno);
- }
- if (!android::base::StartsWith(big_file_->path, kUserDataDevice)) {
- return AssertionFailure() << "Temp file allocated to " << big_file_->path << ", not in "
- << kUserDataDevice;
- }
- uint64_t next_consume = std::min(available_space_ - max_free_space,
- (uint64_t)std::numeric_limits<off_t>::max());
- off_t allocated = 0;
- while (next_consume > 0 && free_space_ > max_free_space) {
- int status = fallocate(big_file_->fd, 0, allocated, next_consume);
- if (status == -1 && errno == ENOSPC) {
- next_consume /= 2;
- continue;
- }
- if (status == -1) {
- return AssertionFailure() << strerror(errno);
- }
- allocated += next_consume;
-
- res = ReadUserdataStats();
- if (!res) return res;
- }
-
- LOG(INFO) << allocated << " bytes allocated to " << big_file_->path;
- initialized_ = true;
- return AssertionSuccess();
-}
-
-AssertionResult LowSpaceUserdata::ReadUserdataStats() {
- struct statvfs buf;
- if (statvfs(kUserDataDevice, &buf) == -1) {
- return AssertionFailure() << strerror(errno);
- }
- bsize_ = buf.f_bsize;
- free_space_ = bsize_ * buf.f_bfree;
- available_space_ = bsize_ * buf.f_bavail;
- return AssertionSuccess();
-}
-
-uint64_t LowSpaceUserdata::free_space() const {
- CHECK(initialized_);
- return free_space_;
-}
-
-uint64_t LowSpaceUserdata::available_space() const {
- CHECK(initialized_);
- return available_space_;
-}
-
-uint64_t LowSpaceUserdata::bsize() const {
- CHECK(initialized_);
- return bsize_;
-}
-
bool IsVirtualAbEnabled() {
return android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
}
diff --git a/fs_mgr/libsnapshot/update_engine/update_metadata.proto b/fs_mgr/libsnapshot/update_engine/update_metadata.proto
deleted file mode 100644
index 69d72e1..0000000
--- a/fs_mgr/libsnapshot/update_engine/update_metadata.proto
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// Copyright (C) 2020 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.
-//
-
-// A subset of system/update_engine/update_metadata.proto. A separate file is
-// used here because:
-// - The original file is optimized for LITE_RUNTIME, but fuzzing needs
-// reflection.
-// - The definition here has less fields. libsnapshot only uses fields declared
-// here, and all fields declared here are fuzzed by libsnapshot_fuzzer. If
-// libsnapshot uses more fields in system/update_engine/update_metadata.proto
-// in the future, they must be added here too, otherwise it will fail to
-// compile.
-//
-// It is okay that this file is older than
-// system/update_engine/update_metadata.proto as long as the messages defined
-// here can also be parsed by protobuf defined there. However, it is not
-// okay to add fields here without adding them to
-// system/update_engine/update_metadata.proto. Doing so will cause a compiler
-// error when libsnapshot code starts to use these dangling fields.
-
-syntax = "proto2";
-
-package chromeos_update_engine;
-
-message Extent {
- optional uint64 start_block = 1;
- optional uint64 num_blocks = 2;
-}
-
-message PartitionInfo {
- optional uint64 size = 1;
-}
-
-message InstallOperation {
- enum Type {
- SOURCE_COPY = 4;
- // Not used by libsnapshot. Declared here so that the fuzzer has an
- // alternative value to use for |type|.
- ZERO = 6;
- }
- required Type type = 1;
- repeated Extent src_extents = 4;
- repeated Extent dst_extents = 6;
-}
-
-message PartitionUpdate {
- required string partition_name = 1;
- optional PartitionInfo new_partition_info = 7;
- repeated InstallOperation operations = 8;
- optional Extent hash_tree_extent = 11;
- optional Extent fec_extent = 15;
- optional uint64 estimate_cow_size = 19;
-}
-
-message DynamicPartitionGroup {
- required string name = 1;
- optional uint64 size = 2;
- repeated string partition_names = 3;
-}
-
-message DynamicPartitionMetadata {
- repeated DynamicPartitionGroup groups = 1;
- optional bool vabc_enabled = 3;
- optional string vabc_compression_param = 4;
- optional uint32 cow_version = 5;
-}
-
-message DeltaArchiveManifest {
- repeated PartitionUpdate partitions = 13;
- optional DynamicPartitionMetadata dynamic_partition_metadata = 15;
- optional bool partial_update = 16;
-}
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index a98bf0e..1ffa89c 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -29,6 +29,7 @@
#include <fs_mgr/roots.h>
#include <liblp/property_fetcher.h>
+using android::dm::DeviceMapper;
using android::dm::kSectorSize;
using android::fiemap::FiemapStatus;
using android::fs_mgr::EnsurePathMounted;
@@ -251,7 +252,10 @@
LOG(INFO) << "Userspace snapshots disabled for testing";
return false;
}
-
+ if (!KernelSupportsCompressedSnapshots()) {
+ LOG(ERROR) << "Userspace snapshots requested, but no kernel support is available.";
+ return false;
+ }
return true;
}
@@ -278,5 +282,10 @@
return fetcher->GetBoolProperty("snapuserd.test.dm.snapshots", false);
}
+bool KernelSupportsCompressedSnapshots() {
+ auto& dm = DeviceMapper::Instance();
+ return dm.GetTargetByName("user", nullptr);
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 8c4c7c6..370f3c4 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -127,6 +127,8 @@
void AppendExtent(google::protobuf::RepeatedPtrField<chromeos_update_engine::Extent>* extents,
uint64_t start_block, uint64_t num_blocks);
+bool KernelSupportsCompressedSnapshots();
+
bool GetLegacyCompressionEnabledProperty();
bool GetUserspaceSnapshotsEnabledProperty();
bool GetIouringEnabledProperty();
diff --git a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
index ac0dfbd..bbeabd5 100644
--- a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
+++ b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
@@ -37,6 +37,7 @@
using KiB = Size<10>;
using MiB = Size<20>;
using GiB = Size<30>;
+using TiB = Size<40>;
constexpr B operator""_B(unsigned long long v) { // NOLINT
return B{v};
@@ -54,6 +55,10 @@
return GiB{v};
}
+constexpr TiB operator""_TiB(unsigned long long v) { // NOLINT
+ return TiB{v};
+}
+
template <typename Dest, typename Src>
constexpr Dest size_cast(Src src) {
if (Src::power < Dest::power) {
@@ -69,6 +74,7 @@
static_assert(1_KiB == 1 << 10);
static_assert(1_MiB == 1 << 20);
static_assert(1_GiB == 1 << 30);
+static_assert(1_TiB == 1ULL << 40);
static_assert(size_cast<KiB>(1_B).count() == 0);
static_assert(size_cast<KiB>(1024_B).count() == 1);
static_assert(size_cast<KiB>(1_MiB).count() == 1024);
diff --git a/fs_mgr/libvbmeta/utility.h b/fs_mgr/libvbmeta/utility.h
index 91db0ad..ab9828d 100644
--- a/fs_mgr/libvbmeta/utility.h
+++ b/fs_mgr/libvbmeta/utility.h
@@ -19,7 +19,7 @@
#include <android-base/logging.h>
#include <android-base/result.h>
-#define VBMETA_TAG "[libvbmeta]"
+#define VBMETA_TAG "[libvbmeta] "
#define LWARN LOG(WARNING) << VBMETA_TAG
#define LINFO LOG(INFO) << VBMETA_TAG
#define LERROR LOG(ERROR) << VBMETA_TAG
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index e33681c..5f889ca 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -497,6 +497,7 @@
EXPECT_EQ("none0", entry->mount_point);
{
FstabEntry::FsMgrFlags flags = {};
+ flags.file_encryption = true;
EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
EXPECT_EQ("", entry->metadata_key_dir);
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index b8b34e2..4d771fa 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -55,6 +55,21 @@
}
TEST(fs, PartitionTypes) {
+ // Requirements only apply to Android 13+, 5.10+ devices.
+ int vsr_level = GetVsrLevel();
+ if (vsr_level < __ANDROID_API_T__) {
+ GTEST_SKIP();
+ }
+
+ struct utsname uts;
+ ASSERT_EQ(uname(&uts), 0);
+
+ unsigned int major, minor;
+ ASSERT_EQ(sscanf(uts.release, "%u.%u", &major, &minor), 2);
+ if (major < 5 || (major == 5 && minor < 10)) {
+ GTEST_SKIP();
+ }
+
android::fs_mgr::Fstab fstab;
ASSERT_TRUE(android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab));
@@ -64,7 +79,10 @@
ASSERT_TRUE(android::base::Readlink("/dev/block/by-name/super", &super_bdev));
ASSERT_TRUE(android::base::Readlink("/dev/block/by-name/userdata", &userdata_bdev));
- int vsr_level = GetVsrLevel();
+ std::vector<std::string> must_be_f2fs = {"/data"};
+ if (vsr_level >= __ANDROID_API_U__) {
+ must_be_f2fs.emplace_back("/metadata");
+ }
for (const auto& entry : fstab) {
std::string parent_bdev = entry.blk_device;
@@ -90,24 +108,20 @@
continue;
}
- if (vsr_level < __ANDROID_API_T__) {
- continue;
- }
- if (vsr_level == __ANDROID_API_T__ && parent_bdev != super_bdev) {
- // Only check for dynamic partitions at this VSR level.
- continue;
- }
-
if (entry.flags & MS_RDONLY) {
- std::vector<std::string> allowed = {"erofs", "ext4"};
- if (vsr_level == __ANDROID_API_T__) {
- allowed.emplace_back("f2fs");
+ if (parent_bdev != super_bdev) {
+ // Ignore non-AOSP partitions (eg anything outside of super).
+ continue;
}
+ std::vector<std::string> allowed = {"erofs", "ext4", "f2fs"};
EXPECT_NE(std::find(allowed.begin(), allowed.end(), entry.fs_type), allowed.end())
<< entry.mount_point;
} else {
- EXPECT_NE(entry.fs_type, "ext4") << entry.mount_point;
+ if (std::find(must_be_f2fs.begin(), must_be_f2fs.end(), entry.mount_point) !=
+ must_be_f2fs.end()) {
+ EXPECT_EQ(entry.fs_type, "f2fs") << entry.mount_point;
+ }
}
}
}
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 62ca162..7273087 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -33,6 +33,7 @@
#include <ios>
#include <iostream>
#include <map>
+#include <optional>
#include <sstream>
#include <string>
#include <vector>
@@ -52,6 +53,7 @@
std::cerr << " getpath <dm-name>" << std::endl;
std::cerr << " getuuid <dm-name>" << std::endl;
std::cerr << " info <dm-name>" << std::endl;
+ std::cerr << " replace <dm-name> <targets...>" << std::endl;
std::cerr << " status <dm-name>" << std::endl;
std::cerr << " resume <dm-name>" << std::endl;
std::cerr << " suspend <dm-name>" << std::endl;
@@ -183,6 +185,8 @@
}
std::string control_device = NextArg();
return std::make_unique<DmTargetUser>(start_sector, num_sectors, control_device);
+ } else if (target_type == "error") {
+ return std::make_unique<DmTargetError>(start_sector, num_sectors);
} else {
std::cerr << "Unrecognized target type: " << target_type << std::endl;
return nullptr;
@@ -206,16 +210,26 @@
char** argv_;
};
-static bool parse_table_args(DmTable* table, int argc, char** argv) {
+struct TableArgs {
+ DmTable table;
+ bool suspended = false;
+};
+
+static std::optional<TableArgs> parse_table_args(int argc, char** argv) {
+ TableArgs out;
+
// Parse extended options first.
int arg_index = 1;
while (arg_index < argc && argv[arg_index][0] == '-') {
if (strcmp(argv[arg_index], "-ro") == 0) {
- table->set_readonly(true);
+ out.table.set_readonly(true);
+ arg_index++;
+ } else if (strcmp(argv[arg_index], "-suspended") == 0) {
+ out.suspended = true;
arg_index++;
} else {
std::cerr << "Unrecognized option: " << argv[arg_index] << std::endl;
- return -EINVAL;
+ return {};
}
}
@@ -223,37 +237,44 @@
TargetParser parser(argc - arg_index, argv + arg_index);
while (parser.More()) {
std::unique_ptr<DmTarget> target = parser.Next();
- if (!target || !table->AddTarget(std::move(target))) {
- return -EINVAL;
+ if (!target || !out.table.AddTarget(std::move(target))) {
+ return {};
}
}
- if (table->num_targets() == 0) {
+ if (out.table.num_targets() == 0) {
std::cerr << "Must define at least one target." << std::endl;
- return -EINVAL;
+ return {};
}
- return 0;
+ return {std::move(out)};
}
static int DmCreateCmdHandler(int argc, char** argv) {
if (argc < 1) {
- std::cerr << "Usage: dmctl create <dm-name> [-ro] <targets...>" << std::endl;
+ std::cerr << "Usage: dmctl create <dm-name> [--suspended] [-ro] <targets...>" << std::endl;
return -EINVAL;
}
std::string name = argv[0];
- DmTable table;
- int ret = parse_table_args(&table, argc, argv);
- if (ret) {
- return ret;
+ auto table_args = parse_table_args(argc, argv);
+ if (!table_args) {
+ return -EINVAL;
}
std::string ignore_path;
DeviceMapper& dm = DeviceMapper::Instance();
- if (!dm.CreateDevice(name, table, &ignore_path, 5s)) {
+ if (!dm.CreateEmptyDevice(name)) {
std::cerr << "Failed to create device-mapper device with name: " << name << std::endl;
return -EIO;
}
+ if (!dm.LoadTable(name, table_args->table)) {
+ std::cerr << "Failed to load table for dm device: " << name << std::endl;
+ return -EIO;
+ }
+ if (!table_args->suspended && !dm.ChangeState(name, DmDeviceState::ACTIVE)) {
+ std::cerr << "Failed to activate table for " << name << std::endl;
+ return -EIO;
+ }
return 0;
}
@@ -269,7 +290,6 @@
std::cerr << "Failed to delete [" << name << "]" << std::endl;
return -EIO;
}
-
return 0;
}
@@ -280,17 +300,20 @@
}
std::string name = argv[0];
- DmTable table;
- int ret = parse_table_args(&table, argc, argv);
- if (ret) {
- return ret;
+ auto table_args = parse_table_args(argc, argv);
+ if (!table_args) {
+ return -EINVAL;
}
DeviceMapper& dm = DeviceMapper::Instance();
- if (!dm.LoadTableAndActivate(name, table)) {
+ if (!dm.LoadTable(name, table_args->table)) {
std::cerr << "Failed to replace device-mapper table to: " << name << std::endl;
return -EIO;
}
+ if (!table_args->suspended && !dm.ChangeState(name, DmDeviceState::ACTIVE)) {
+ std::cerr << "Failed to activate table for " << name << std::endl;
+ return -EIO;
+ }
return 0;
}
diff --git a/gatekeeperd/Android.bp b/gatekeeperd/Android.bp
index 838f734..534fc1a 100644
--- a/gatekeeperd/Android.bp
+++ b/gatekeeperd/Android.bp
@@ -18,8 +18,8 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_binary {
- name: "gatekeeperd",
+cc_defaults {
+ name: "gatekeeperd_defaults",
cflags: [
"-Wall",
"-Wextra",
@@ -52,6 +52,16 @@
static_libs: ["libscrypt_static"],
include_dirs: ["external/scrypt/lib/crypto"],
+}
+
+cc_binary {
+ name: "gatekeeperd",
+ defaults: [
+ "gatekeeperd_defaults",
+ ],
+ srcs: [
+ "main.cpp",
+ ],
init_rc: ["gatekeeperd.rc"],
}
@@ -88,3 +98,20 @@
"libbinder",
],
}
+
+cc_fuzz {
+ name: "gatekeeperd_service_fuzzer",
+ defaults: [
+ "gatekeeperd_defaults",
+ "service_fuzzer_defaults"
+ ],
+ srcs: [
+ "fuzzer/GateKeeperServiceFuzzer.cpp",
+ ],
+ fuzz_config: {
+ cc: [
+ "subrahmanyaman@google.com",
+ "swillden@google.com",
+ ],
+ },
+}
\ No newline at end of file
diff --git a/gatekeeperd/OWNERS b/gatekeeperd/OWNERS
index 9c99c6e..04cd19e 100644
--- a/gatekeeperd/OWNERS
+++ b/gatekeeperd/OWNERS
@@ -1,2 +1,5 @@
+# Bug component: 1124862
+drysdale@google.com
+oarbildo@google.com
+subrahmanyaman@google.com
swillden@google.com
-jdanis@google.com
diff --git a/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp b/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp
new file mode 100644
index 0000000..bc0d5fe
--- /dev/null
+++ b/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 <fuzzbinder/libbinder_driver.h>
+
+#include "gatekeeperd.h"
+
+using android::fuzzService;
+using android::GateKeeperProxy;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto gatekeeperService = new GateKeeperProxy();
+ fuzzService(gatekeeperService, FuzzedDataProvider(data, size));
+ return 0;
+}
\ No newline at end of file
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 76fcd55..bdfb7f6 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -13,11 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#define LOG_TAG "gatekeeperd"
-#include <android/service/gatekeeper/BnGateKeeperService.h>
-#include <gatekeeper/GateKeeperResponse.h>
+#include "gatekeeperd.h"
#include <endian.h>
#include <errno.h>
@@ -39,25 +37,18 @@
#include <log/log.h>
#include <utils/String16.h>
-#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
#include <aidl/android/security/authorization/IKeystoreAuthorization.h>
-#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
#include <hidl/HidlSupport.h>
using android::sp;
using android::hardware::Return;
using android::hardware::gatekeeper::V1_0::GatekeeperResponse;
using android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
-using android::hardware::gatekeeper::V1_0::IGatekeeper;
using AidlGatekeeperEnrollResp = aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
using AidlGatekeeperVerifyResp = aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
-using AidlIGatekeeper = aidl::android::hardware::gatekeeper::IGatekeeper;
-using ::android::binder::Status;
-using ::android::service::gatekeeper::BnGateKeeperService;
-using GKResponse = ::android::service::gatekeeper::GateKeeperResponse;
using GKResponseCode = ::android::service::gatekeeper::ResponseCode;
using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
@@ -70,172 +61,184 @@
static const String16 DUMP_PERMISSION("android.permission.DUMP");
constexpr const char gatekeeperServiceName[] = "android.hardware.gatekeeper.IGatekeeper/default";
-class GateKeeperProxy : public BnGateKeeperService {
- public:
- GateKeeperProxy() {
- clear_state_if_needed_done = false;
- hw_device = IGatekeeper::getService();
- ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(gatekeeperServiceName));
+GateKeeperProxy::GateKeeperProxy() {
+ clear_state_if_needed_done = false;
+ if (AServiceManager_isDeclared(gatekeeperServiceName)) {
+ ::ndk::SpAIBinder ks2Binder(AServiceManager_waitForService(gatekeeperServiceName));
aidl_hw_device = AidlIGatekeeper::fromBinder(ks2Binder);
- is_running_gsi = android::base::GetBoolProperty(android::gsi::kGsiBootedProp, false);
+ }
+ if (!aidl_hw_device) {
+ hw_device = IGatekeeper::getService();
+ }
+ is_running_gsi = android::base::GetBoolProperty(android::gsi::kGsiBootedProp, false);
- if (!aidl_hw_device && !hw_device) {
- LOG(ERROR) << "Could not find Gatekeeper device, which makes me very sad.";
+ if (!aidl_hw_device && !hw_device) {
+ LOG(ERROR) << "Could not find Gatekeeper device, which makes me very sad.";
+ }
+}
+
+void GateKeeperProxy::store_sid(uint32_t userId, uint64_t sid) {
+ char filename[21];
+ snprintf(filename, sizeof(filename), "%u", userId);
+ int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ ALOGE("could not open file: %s: %s", filename, strerror(errno));
+ return;
+ }
+ write(fd, &sid, sizeof(sid));
+ close(fd);
+}
+
+void GateKeeperProxy::clear_state_if_needed() {
+ if (clear_state_if_needed_done) {
+ return;
+ }
+
+ if (mark_cold_boot() && !is_running_gsi) {
+ ALOGI("cold boot: clearing state");
+ if (aidl_hw_device) {
+ aidl_hw_device->deleteAllUsers();
+ } else if (hw_device) {
+ hw_device->deleteAllUsers([](const GatekeeperResponse&) {});
}
}
- virtual ~GateKeeperProxy() {}
+ clear_state_if_needed_done = true;
+}
- void store_sid(uint32_t userId, uint64_t sid) {
- char filename[21];
- snprintf(filename, sizeof(filename), "%u", userId);
+bool GateKeeperProxy::mark_cold_boot() {
+ const char* filename = ".coldboot";
+ if (access(filename, F_OK) == -1) {
int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0) {
- ALOGE("could not open file: %s: %s", filename, strerror(errno));
- return;
+ ALOGE("could not open file: %s : %s", filename, strerror(errno));
+ return false;
}
- write(fd, &sid, sizeof(sid));
close(fd);
+ return true;
+ }
+ return false;
+}
+
+void GateKeeperProxy::maybe_store_sid(uint32_t userId, uint64_t sid) {
+ char filename[21];
+ snprintf(filename, sizeof(filename), "%u", userId);
+ if (access(filename, F_OK) == -1) {
+ store_sid(userId, sid);
+ }
+}
+
+uint64_t GateKeeperProxy::read_sid(uint32_t userId) {
+ char filename[21];
+ uint64_t sid;
+ snprintf(filename, sizeof(filename), "%u", userId);
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) return 0;
+ read(fd, &sid, sizeof(sid));
+ close(fd);
+ return sid;
+}
+
+void GateKeeperProxy::clear_sid(uint32_t userId) {
+ char filename[21];
+ snprintf(filename, sizeof(filename), "%u", userId);
+ if (remove(filename) < 0 && errno != ENOENT) {
+ ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno));
+ store_sid(userId, 0);
+ }
+}
+
+Status GateKeeperProxy::adjust_userId(uint32_t userId, uint32_t* hw_userId) {
+ static constexpr uint32_t kGsiOffset = 1000000;
+ if (userId >= kGsiOffset) {
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
- void clear_state_if_needed() {
- if (clear_state_if_needed_done) {
- return;
- }
-
- if (mark_cold_boot() && !is_running_gsi) {
- ALOGI("cold boot: clearing state");
- if (aidl_hw_device) {
- aidl_hw_device->deleteAllUsers();
- } else if (hw_device) {
- hw_device->deleteAllUsers([](const GatekeeperResponse&) {});
- }
- }
-
- clear_state_if_needed_done = true;
+ if ((aidl_hw_device == nullptr) && (hw_device == nullptr)) {
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}
- bool mark_cold_boot() {
- const char* filename = ".coldboot";
- if (access(filename, F_OK) == -1) {
- int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
- if (fd < 0) {
- ALOGE("could not open file: %s : %s", filename, strerror(errno));
- return false;
- }
- close(fd);
- return true;
- }
- return false;
+ if (is_running_gsi) {
+ *hw_userId = userId + kGsiOffset;
+ return Status::ok();
}
-
- void maybe_store_sid(uint32_t userId, uint64_t sid) {
- char filename[21];
- snprintf(filename, sizeof(filename), "%u", userId);
- if (access(filename, F_OK) == -1) {
- store_sid(userId, sid);
- }
- }
-
- uint64_t read_sid(uint32_t userId) {
- char filename[21];
- uint64_t sid;
- snprintf(filename, sizeof(filename), "%u", userId);
- int fd = open(filename, O_RDONLY);
- if (fd < 0) return 0;
- read(fd, &sid, sizeof(sid));
- close(fd);
- return sid;
- }
-
- void clear_sid(uint32_t userId) {
- char filename[21];
- snprintf(filename, sizeof(filename), "%u", userId);
- if (remove(filename) < 0) {
- ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno));
- store_sid(userId, 0);
- }
- }
-
- // This should only be called on userIds being passed to the GateKeeper HAL. It ensures that
- // secure storage shared across a GSI image and a host image will not overlap.
- uint32_t adjust_userId(uint32_t userId) {
- static constexpr uint32_t kGsiOffset = 1000000;
- CHECK(userId < kGsiOffset);
- CHECK((aidl_hw_device != nullptr) || (hw_device != nullptr));
- if (is_running_gsi) {
- return userId + kGsiOffset;
- }
- return userId;
- }
+ *hw_userId = userId;
+ return Status::ok();
+}
#define GK_ERROR *gkResponse = GKResponse::error(), Status::ok()
- Status enroll(int32_t userId, const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
- const std::optional<std::vector<uint8_t>>& currentPassword,
- const std::vector<uint8_t>& desiredPassword, GKResponse* gkResponse) override {
- IPCThreadState* ipc = IPCThreadState::self();
- const int calling_pid = ipc->getCallingPid();
- const int calling_uid = ipc->getCallingUid();
- if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
- return GK_ERROR;
- }
+Status GateKeeperProxy::enroll(int32_t userId,
+ const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
+ const std::optional<std::vector<uint8_t>>& currentPassword,
+ const std::vector<uint8_t>& desiredPassword,
+ GKResponse* gkResponse) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int calling_pid = ipc->getCallingPid();
+ const int calling_uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+ return GK_ERROR;
+ }
- // Make sure to clear any state from before factory reset as soon as a credential is
- // enrolled (which may happen during device setup).
- clear_state_if_needed();
+ // Make sure to clear any state from before factory reset as soon as a credential is
+ // enrolled (which may happen during device setup).
+ clear_state_if_needed();
- // need a desired password to enroll
- if (desiredPassword.size() == 0) return GK_ERROR;
+ // need a desired password to enroll
+ if (desiredPassword.size() == 0) return GK_ERROR;
- if (!aidl_hw_device && !hw_device) {
- LOG(ERROR) << "has no HAL to talk to";
- return GK_ERROR;
- }
+ if (!aidl_hw_device && !hw_device) {
+ LOG(ERROR) << "has no HAL to talk to";
+ return GK_ERROR;
+ }
- android::hardware::hidl_vec<uint8_t> curPwdHandle;
- android::hardware::hidl_vec<uint8_t> curPwd;
+ android::hardware::hidl_vec<uint8_t> curPwdHandle;
+ android::hardware::hidl_vec<uint8_t> curPwd;
- if (currentPasswordHandle && currentPassword) {
- if (hw_device) {
- // Hidl Implementations expects passwordHandle to be in
- // gatekeeper::password_handle_t format.
- if (currentPasswordHandle->size() != sizeof(gatekeeper::password_handle_t)) {
- LOG(INFO) << "Password handle has wrong length";
- return GK_ERROR;
- }
- }
- curPwdHandle.setToExternal(const_cast<uint8_t*>(currentPasswordHandle->data()),
- currentPasswordHandle->size());
- curPwd.setToExternal(const_cast<uint8_t*>(currentPassword->data()),
- currentPassword->size());
- }
-
- android::hardware::hidl_vec<uint8_t> newPwd;
- newPwd.setToExternal(const_cast<uint8_t*>(desiredPassword.data()), desiredPassword.size());
-
- uint32_t hw_userId = adjust_userId(userId);
- uint64_t secureUserId = 0;
- if (aidl_hw_device) {
- // AIDL gatekeeper service
- AidlGatekeeperEnrollResp rsp;
- auto result = aidl_hw_device->enroll(hw_userId, curPwdHandle, curPwd, newPwd, &rsp);
- if (!result.isOk()) {
- LOG(ERROR) << "enroll transaction failed";
+ if (currentPasswordHandle && currentPassword) {
+ if (hw_device) {
+ // Hidl Implementations expects passwordHandle to be in
+ // gatekeeper::password_handle_t format.
+ if (currentPasswordHandle->size() != sizeof(gatekeeper::password_handle_t)) {
+ LOG(INFO) << "Password handle has wrong length";
return GK_ERROR;
}
- if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
- *gkResponse = GKResponse::ok({rsp.data.begin(), rsp.data.end()});
- secureUserId = static_cast<uint64_t>(rsp.secureUserId);
- } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT &&
- rsp.timeoutMs > 0) {
- *gkResponse = GKResponse::retry(rsp.timeoutMs);
- } else {
- *gkResponse = GKResponse::error();
- }
- } else if (hw_device) {
- // HIDL gatekeeper service
- Return<void> hwRes = hw_device->enroll(
+ }
+ curPwdHandle.setToExternal(const_cast<uint8_t*>(currentPasswordHandle->data()),
+ currentPasswordHandle->size());
+ curPwd.setToExternal(const_cast<uint8_t*>(currentPassword->data()),
+ currentPassword->size());
+ }
+
+ android::hardware::hidl_vec<uint8_t> newPwd;
+ newPwd.setToExternal(const_cast<uint8_t*>(desiredPassword.data()), desiredPassword.size());
+
+ uint32_t hw_userId = 0;
+ Status result = adjust_userId(userId, &hw_userId);
+ if (!result.isOk()) {
+ return result;
+ }
+
+ uint64_t secureUserId = 0;
+ if (aidl_hw_device) {
+ // AIDL gatekeeper service
+ AidlGatekeeperEnrollResp rsp;
+ auto result = aidl_hw_device->enroll(hw_userId, curPwdHandle, curPwd, newPwd, &rsp);
+ if (!result.isOk()) {
+ LOG(ERROR) << "enroll transaction failed";
+ return GK_ERROR;
+ }
+ if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
+ *gkResponse = GKResponse::ok({rsp.data.begin(), rsp.data.end()});
+ secureUserId = static_cast<uint64_t>(rsp.secureUserId);
+ } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT && rsp.timeoutMs > 0) {
+ *gkResponse = GKResponse::retry(rsp.timeoutMs);
+ } else {
+ *gkResponse = GKResponse::error();
+ }
+ } else if (hw_device) {
+ // HIDL gatekeeper service
+ Return<void> hwRes = hw_device->enroll(
hw_userId, curPwdHandle, curPwd, newPwd,
[&gkResponse](const GatekeeperResponse& rsp) {
if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
@@ -247,110 +250,115 @@
*gkResponse = GKResponse::error();
}
});
- if (!hwRes.isOk()) {
- LOG(ERROR) << "enroll transaction failed";
+ if (!hwRes.isOk()) {
+ LOG(ERROR) << "enroll transaction failed";
+ return GK_ERROR;
+ }
+ if (gkResponse->response_code() == GKResponseCode::OK) {
+ if (gkResponse->payload().size() != sizeof(gatekeeper::password_handle_t)) {
+ LOG(ERROR) << "HAL returned password handle of invalid length "
+ << gkResponse->payload().size();
return GK_ERROR;
}
- if (gkResponse->response_code() == GKResponseCode::OK) {
- if (gkResponse->payload().size() != sizeof(gatekeeper::password_handle_t)) {
- LOG(ERROR) << "HAL returned password handle of invalid length "
- << gkResponse->payload().size();
- return GK_ERROR;
- }
- const gatekeeper::password_handle_t* handle =
+ const gatekeeper::password_handle_t* handle =
reinterpret_cast<const gatekeeper::password_handle_t*>(
- gkResponse->payload().data());
- secureUserId = handle->user_id;
- }
+ gkResponse->payload().data());
+ secureUserId = handle->user_id;
}
-
- if (gkResponse->response_code() == GKResponseCode::OK && !gkResponse->should_reenroll()) {
- store_sid(userId, secureUserId);
-
- GKResponse verifyResponse;
- // immediately verify this password so we don't ask the user to enter it again
- // if they just created it.
- auto status = verify(userId, gkResponse->payload(), desiredPassword, &verifyResponse);
- if (!status.isOk() || verifyResponse.response_code() != GKResponseCode::OK) {
- LOG(ERROR) << "Failed to verify password after enrolling";
- }
- }
-
- return Status::ok();
}
- Status verify(int32_t userId, const ::std::vector<uint8_t>& enrolledPasswordHandle,
- const ::std::vector<uint8_t>& providedPassword, GKResponse* gkResponse) override {
- return verifyChallenge(userId, 0 /* challenge */, enrolledPasswordHandle, providedPassword,
- gkResponse);
+ if (gkResponse->response_code() == GKResponseCode::OK && !gkResponse->should_reenroll()) {
+ store_sid(userId, secureUserId);
+
+ GKResponse verifyResponse;
+ // immediately verify this password so we don't ask the user to enter it again
+ // if they just created it.
+ auto status = verify(userId, gkResponse->payload(), desiredPassword, &verifyResponse);
+ if (!status.isOk() || verifyResponse.response_code() != GKResponseCode::OK) {
+ LOG(ERROR) << "Failed to verify password after enrolling";
+ }
}
- Status verifyChallenge(int32_t userId, int64_t challenge,
- const std::vector<uint8_t>& enrolledPasswordHandle,
- const std::vector<uint8_t>& providedPassword,
- GKResponse* gkResponse) override {
- IPCThreadState* ipc = IPCThreadState::self();
- const int calling_pid = ipc->getCallingPid();
- const int calling_uid = ipc->getCallingUid();
- if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+ return Status::ok();
+}
+
+Status GateKeeperProxy::verify(int32_t userId, const ::std::vector<uint8_t>& enrolledPasswordHandle,
+ const ::std::vector<uint8_t>& providedPassword,
+ GKResponse* gkResponse) {
+ return verifyChallenge(userId, 0 /* challenge */, enrolledPasswordHandle, providedPassword,
+ gkResponse);
+}
+
+Status GateKeeperProxy::verifyChallenge(int32_t userId, int64_t challenge,
+ const std::vector<uint8_t>& enrolledPasswordHandle,
+ const std::vector<uint8_t>& providedPassword,
+ GKResponse* gkResponse) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int calling_pid = ipc->getCallingPid();
+ const int calling_uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+ return GK_ERROR;
+ }
+
+ // can't verify if we're missing either param
+ if (enrolledPasswordHandle.size() == 0 || providedPassword.size() == 0) return GK_ERROR;
+
+ if (!aidl_hw_device && !hw_device) {
+ LOG(ERROR) << "has no HAL to talk to";
+ return GK_ERROR;
+ }
+
+ if (hw_device) {
+ // Hidl Implementations expects passwordHandle to be in gatekeeper::password_handle_t
+ if (enrolledPasswordHandle.size() != sizeof(gatekeeper::password_handle_t)) {
+ LOG(INFO) << "Password handle has wrong length";
return GK_ERROR;
}
+ }
- // can't verify if we're missing either param
- if (enrolledPasswordHandle.size() == 0 || providedPassword.size() == 0) return GK_ERROR;
+ uint32_t hw_userId = 0;
+ Status result = adjust_userId(userId, &hw_userId);
+ if (!result.isOk()) {
+ return result;
+ }
- if (!aidl_hw_device && !hw_device) {
- LOG(ERROR) << "has no HAL to talk to";
+ android::hardware::hidl_vec<uint8_t> curPwdHandle;
+ curPwdHandle.setToExternal(const_cast<uint8_t*>(enrolledPasswordHandle.data()),
+ enrolledPasswordHandle.size());
+ android::hardware::hidl_vec<uint8_t> enteredPwd;
+ enteredPwd.setToExternal(const_cast<uint8_t*>(providedPassword.data()),
+ providedPassword.size());
+
+ uint64_t secureUserId = 0;
+ if (aidl_hw_device) {
+ // AIDL gatekeeper service
+ AidlGatekeeperVerifyResp rsp;
+ auto result = aidl_hw_device->verify(hw_userId, challenge, curPwdHandle, enteredPwd, &rsp);
+ if (!result.isOk()) {
+ LOG(ERROR) << "verify transaction failed";
return GK_ERROR;
}
-
- if (hw_device) {
- // Hidl Implementations expects passwordHandle to be in gatekeeper::password_handle_t
- if (enrolledPasswordHandle.size() != sizeof(gatekeeper::password_handle_t)) {
- LOG(INFO) << "Password handle has wrong length";
- return GK_ERROR;
- }
+ if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
+ secureUserId = rsp.hardwareAuthToken.userId;
+ // Serialize HardwareAuthToken to a vector as hw_auth_token_t.
+ *gkResponse = GKResponse::ok(
+ authToken2AidlVec(rsp.hardwareAuthToken),
+ rsp.statusCode == AidlIGatekeeper::STATUS_REENROLL /* reenroll */);
+ } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT) {
+ *gkResponse = GKResponse::retry(rsp.timeoutMs);
+ } else {
+ *gkResponse = GKResponse::error();
}
-
- uint32_t hw_userId = adjust_userId(userId);
- android::hardware::hidl_vec<uint8_t> curPwdHandle;
- curPwdHandle.setToExternal(const_cast<uint8_t*>(enrolledPasswordHandle.data()),
- enrolledPasswordHandle.size());
- android::hardware::hidl_vec<uint8_t> enteredPwd;
- enteredPwd.setToExternal(const_cast<uint8_t*>(providedPassword.data()),
- providedPassword.size());
-
- uint64_t secureUserId = 0;
- if (aidl_hw_device) {
- // AIDL gatekeeper service
- AidlGatekeeperVerifyResp rsp;
- auto result =
- aidl_hw_device->verify(hw_userId, challenge, curPwdHandle, enteredPwd, &rsp);
- if (!result.isOk()) {
- LOG(ERROR) << "verify transaction failed";
- return GK_ERROR;
- }
- if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
- secureUserId = rsp.hardwareAuthToken.userId;
- // Serialize HardwareAuthToken to a vector as hw_auth_token_t.
- *gkResponse = GKResponse::ok(authToken2AidlVec(rsp.hardwareAuthToken),
- rsp.statusCode ==
- AidlIGatekeeper::STATUS_REENROLL /* reenroll */);
- } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT) {
- *gkResponse = GKResponse::retry(rsp.timeoutMs);
- } else {
- *gkResponse = GKResponse::error();
- }
- } else if (hw_device) {
- // HIDL gatekeeper service
- Return<void> hwRes = hw_device->verify(
+ } else if (hw_device) {
+ // HIDL gatekeeper service
+ Return<void> hwRes = hw_device->verify(
hw_userId, challenge, curPwdHandle, enteredPwd,
[&gkResponse](const GatekeeperResponse& rsp) {
if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
*gkResponse = GKResponse::ok(
- {rsp.data.begin(), rsp.data.end()},
- rsp.code == GatekeeperStatusCode::STATUS_REENROLL /* reenroll */);
+ {rsp.data.begin(), rsp.data.end()},
+ rsp.code == GatekeeperStatusCode::STATUS_REENROLL /* reenroll */);
} else if (rsp.code == GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
*gkResponse = GKResponse::retry(rsp.timeout);
} else {
@@ -358,149 +366,115 @@
}
});
- if (!hwRes.isOk()) {
- LOG(ERROR) << "verify transaction failed";
- return GK_ERROR;
- }
- const gatekeeper::password_handle_t* handle =
- reinterpret_cast<const gatekeeper::password_handle_t*>(
- enrolledPasswordHandle.data());
- secureUserId = handle->user_id;
+ if (!hwRes.isOk()) {
+ LOG(ERROR) << "verify transaction failed";
+ return GK_ERROR;
}
+ const gatekeeper::password_handle_t* handle =
+ reinterpret_cast<const gatekeeper::password_handle_t*>(
+ enrolledPasswordHandle.data());
+ secureUserId = handle->user_id;
+ }
- if (gkResponse->response_code() == GKResponseCode::OK) {
- if (gkResponse->payload().size() != 0) {
- // try to connect to IKeystoreAuthorization AIDL service first.
- AIBinder* authzAIBinder =
- AServiceManager_getService("android.security.authorization");
- ::ndk::SpAIBinder authzBinder(authzAIBinder);
- auto authzService = IKeystoreAuthorization::fromBinder(authzBinder);
- if (authzService) {
- if (gkResponse->payload().size() != sizeof(hw_auth_token_t)) {
- LOG(ERROR) << "Incorrect size of AuthToken payload.";
- return GK_ERROR;
- }
-
- const hw_auth_token_t* hwAuthToken =
- reinterpret_cast<const hw_auth_token_t*>(gkResponse->payload().data());
- HardwareAuthToken authToken;
-
- authToken.timestamp.milliSeconds = betoh64(hwAuthToken->timestamp);
- authToken.challenge = hwAuthToken->challenge;
- authToken.userId = hwAuthToken->user_id;
- authToken.authenticatorId = hwAuthToken->authenticator_id;
- authToken.authenticatorType = static_cast<HardwareAuthenticatorType>(
- betoh32(hwAuthToken->authenticator_type));
- authToken.mac.assign(&hwAuthToken->hmac[0], &hwAuthToken->hmac[32]);
- auto result = authzService->addAuthToken(authToken);
- if (!result.isOk()) {
- LOG(ERROR) << "Failure in sending AuthToken to AuthorizationService.";
- return GK_ERROR;
- }
- } else {
- LOG(ERROR) << "Cannot deliver auth token. Unable to communicate with "
- "Keystore.";
+ if (gkResponse->response_code() == GKResponseCode::OK) {
+ if (gkResponse->payload().size() != 0) {
+ // try to connect to IKeystoreAuthorization AIDL service first.
+ AIBinder* authzAIBinder = AServiceManager_getService("android.security.authorization");
+ ::ndk::SpAIBinder authzBinder(authzAIBinder);
+ auto authzService = IKeystoreAuthorization::fromBinder(authzBinder);
+ if (authzService) {
+ if (gkResponse->payload().size() != sizeof(hw_auth_token_t)) {
+ LOG(ERROR) << "Incorrect size of AuthToken payload.";
return GK_ERROR;
}
+
+ const hw_auth_token_t* hwAuthToken =
+ reinterpret_cast<const hw_auth_token_t*>(gkResponse->payload().data());
+ HardwareAuthToken authToken;
+
+ authToken.timestamp.milliSeconds = betoh64(hwAuthToken->timestamp);
+ authToken.challenge = hwAuthToken->challenge;
+ authToken.userId = hwAuthToken->user_id;
+ authToken.authenticatorId = hwAuthToken->authenticator_id;
+ authToken.authenticatorType = static_cast<HardwareAuthenticatorType>(
+ betoh32(hwAuthToken->authenticator_type));
+ authToken.mac.assign(&hwAuthToken->hmac[0], &hwAuthToken->hmac[32]);
+ auto result = authzService->addAuthToken(authToken);
+ if (!result.isOk()) {
+ LOG(ERROR) << "Failure in sending AuthToken to AuthorizationService.";
+ return GK_ERROR;
+ }
+ } else {
+ LOG(ERROR) << "Cannot deliver auth token. Unable to communicate with "
+ "Keystore.";
+ return GK_ERROR;
}
-
- maybe_store_sid(userId, secureUserId);
}
- return Status::ok();
+ maybe_store_sid(userId, secureUserId);
}
- Status getSecureUserId(int32_t userId, int64_t* sid) override {
- *sid = read_sid(userId);
- return Status::ok();
- }
-
- Status clearSecureUserId(int32_t userId) override {
- IPCThreadState* ipc = IPCThreadState::self();
- const int calling_pid = ipc->getCallingPid();
- const int calling_uid = ipc->getCallingUid();
- if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
- ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
- return Status::ok();
- }
- clear_sid(userId);
-
- uint32_t hw_userId = adjust_userId(userId);
- if (aidl_hw_device) {
- aidl_hw_device->deleteUser(hw_userId);
- } else if (hw_device) {
- hw_device->deleteUser(hw_userId, [](const GatekeeperResponse&) {});
- }
- return Status::ok();
- }
-
- Status reportDeviceSetupComplete() override {
- IPCThreadState* ipc = IPCThreadState::self();
- const int calling_pid = ipc->getCallingPid();
- const int calling_uid = ipc->getCallingUid();
- if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
- ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
- return Status::ok();
- }
-
- clear_state_if_needed();
- return Status::ok();
- }
-
- status_t dump(int fd, const Vector<String16>&) override {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
- return PERMISSION_DENIED;
- }
-
- if (aidl_hw_device == nullptr && hw_device == nullptr) {
- const char* result = "Device not available";
- write(fd, result, strlen(result) + 1);
- } else {
- const char* result = "OK";
- write(fd, result, strlen(result) + 1);
- }
-
- return OK;
- }
-
- private:
- // AIDL gatekeeper service.
- std::shared_ptr<AidlIGatekeeper> aidl_hw_device;
- // HIDL gatekeeper service.
- sp<IGatekeeper> hw_device;
-
- bool clear_state_if_needed_done;
- bool is_running_gsi;
-};
-} // namespace android
-
-int main(int argc, char* argv[]) {
- ALOGI("Starting gatekeeperd...");
- if (argc < 2) {
- ALOGE("A directory must be specified!");
- return 1;
- }
- if (chdir(argv[1]) == -1) {
- ALOGE("chdir: %s: %s", argv[1], strerror(errno));
- return 1;
- }
-
- android::sp<android::IServiceManager> sm = android::defaultServiceManager();
- android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
- android::status_t ret =
- sm->addService(android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
- if (ret != android::OK) {
- ALOGE("Couldn't register binder service!");
- return -1;
- }
-
- /*
- * We're the only thread in existence, so we're just going to process
- * Binder transaction as a single-threaded program.
- */
- android::IPCThreadState::self()->joinThreadPool();
- return 0;
+ return Status::ok();
}
+
+Status GateKeeperProxy::getSecureUserId(int32_t userId, int64_t* sid) {
+ *sid = read_sid(userId);
+ return Status::ok();
+}
+
+Status GateKeeperProxy::clearSecureUserId(int32_t userId) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int calling_pid = ipc->getCallingPid();
+ const int calling_uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+ ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
+ return Status::ok();
+ }
+ clear_sid(userId);
+
+ uint32_t hw_userId = 0;
+ Status result = adjust_userId(userId, &hw_userId);
+ if (!result.isOk()) {
+ return result;
+ }
+
+ if (aidl_hw_device) {
+ aidl_hw_device->deleteUser(hw_userId);
+ } else if (hw_device) {
+ hw_device->deleteUser(hw_userId, [](const GatekeeperResponse&) {});
+ }
+ return Status::ok();
+}
+
+Status GateKeeperProxy::reportDeviceSetupComplete() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int calling_pid = ipc->getCallingPid();
+ const int calling_uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+ ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
+ return Status::ok();
+ }
+
+ clear_state_if_needed();
+ return Status::ok();
+}
+
+status_t GateKeeperProxy::dump(int fd, const Vector<String16>&) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
+ return PERMISSION_DENIED;
+ }
+
+ if (aidl_hw_device == nullptr && hw_device == nullptr) {
+ const char* result = "Device not available";
+ write(fd, result, strlen(result) + 1);
+ } else {
+ const char* result = "OK";
+ write(fd, result, strlen(result) + 1);
+ }
+
+ return OK;
+}
+} // namespace android
diff --git a/gatekeeperd/gatekeeperd.h b/gatekeeperd/gatekeeperd.h
new file mode 100644
index 0000000..b1f08c6
--- /dev/null
+++ b/gatekeeperd/gatekeeperd.h
@@ -0,0 +1,83 @@
+/*
+ * 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 <aidl/android/hardware/gatekeeper/IGatekeeper.h>
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+#include <android/service/gatekeeper/BnGateKeeperService.h>
+#include <gatekeeper/GateKeeperResponse.h>
+
+using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
+using AidlIGatekeeper = ::aidl::android::hardware::gatekeeper::IGatekeeper;
+using ::android::binder::Status;
+using ::android::service::gatekeeper::BnGateKeeperService;
+using GKResponse = ::android::service::gatekeeper::GateKeeperResponse;
+
+namespace android {
+
+class GateKeeperProxy : public BnGateKeeperService {
+ public:
+ GateKeeperProxy();
+
+ virtual ~GateKeeperProxy() {}
+
+ void store_sid(uint32_t userId, uint64_t sid);
+
+ void clear_state_if_needed();
+
+ bool mark_cold_boot();
+
+ void maybe_store_sid(uint32_t userId, uint64_t sid);
+
+ uint64_t read_sid(uint32_t userId);
+
+ void clear_sid(uint32_t userId);
+
+ // This should only be called on userIds being passed to the GateKeeper HAL. It ensures that
+ // secure storage shared across a GSI image and a host image will not overlap.
+ Status adjust_userId(uint32_t userId, uint32_t* hw_userId);
+
+#define GK_ERROR *gkResponse = GKResponse::error(), Status::ok()
+
+ Status enroll(int32_t userId, const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
+ const std::optional<std::vector<uint8_t>>& currentPassword,
+ const std::vector<uint8_t>& desiredPassword, GKResponse* gkResponse) override;
+
+ Status verify(int32_t userId, const ::std::vector<uint8_t>& enrolledPasswordHandle,
+ const ::std::vector<uint8_t>& providedPassword, GKResponse* gkResponse) override;
+
+ Status verifyChallenge(int32_t userId, int64_t challenge,
+ const std::vector<uint8_t>& enrolledPasswordHandle,
+ const std::vector<uint8_t>& providedPassword,
+ GKResponse* gkResponse) override;
+
+ Status getSecureUserId(int32_t userId, int64_t* sid) override;
+
+ Status clearSecureUserId(int32_t userId) override;
+
+ Status reportDeviceSetupComplete() override;
+
+ status_t dump(int fd, const Vector<String16>&) override;
+
+ private:
+ // AIDL gatekeeper service.
+ std::shared_ptr<AidlIGatekeeper> aidl_hw_device;
+ // HIDL gatekeeper service.
+ sp<IGatekeeper> hw_device;
+
+ bool clear_state_if_needed_done;
+ bool is_running_gsi;
+};
+} // namespace android
diff --git a/gatekeeperd/main.cpp b/gatekeeperd/main.cpp
new file mode 100644
index 0000000..a01f9de
--- /dev/null
+++ b/gatekeeperd/main.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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 <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <log/log.h>
+
+#include "gatekeeperd.h"
+
+int main(int argc, char* argv[]) {
+ ALOGI("Starting gatekeeperd...");
+ if (argc < 2) {
+ ALOGE("A directory must be specified!");
+ return 1;
+ }
+ if (chdir(argv[1]) == -1) {
+ ALOGE("chdir: %s: %s", argv[1], strerror(errno));
+ return 1;
+ }
+
+ android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+ android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
+ android::status_t ret = sm->addService(
+ android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
+ if (ret != android::OK) {
+ ALOGE("Couldn't register binder service!");
+ return 1;
+ }
+
+ /*
+ * We're the only thread in existence, so we're just going to process
+ * Binder transaction as a single-threaded program.
+ */
+ android::IPCThreadState::self()->joinThreadPool();
+ return 1;
+}
diff --git a/healthd/Android.bp b/healthd/Android.bp
index a090b74..235303f 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -2,18 +2,8 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_headers {
- name: "libhealthd_headers",
- vendor_available: true,
- recovery_available: true,
- export_include_dirs: ["include"],
- header_libs: ["libbatteryservice_headers"],
- export_header_lib_headers: ["libbatteryservice_headers"],
-}
-
-cc_library_static {
- name: "libbatterymonitor",
- srcs: ["BatteryMonitor.cpp"],
+cc_defaults {
+ name: "libbatterymonitor_defaults",
cflags: ["-Wall", "-Werror"],
vendor_available: true,
recovery_available: true,
@@ -25,15 +15,89 @@
// Need HealthInfo definition from headers of these shared
// libraries. Clients don't need to link to these.
"android.hardware.health@2.1",
- "android.hardware.health-V1-ndk",
+ ],
+ header_libs: ["libhealthd_headers"],
+ export_header_lib_headers: ["libhealthd_headers"],
+}
+
+cc_defaults {
+ name: "libhealthd_charger_ui_defaults",
+ vendor_available: true,
+ export_include_dirs: [
+ "include",
+ "include_charger",
+ ],
+
+ static_libs: [
+ "libcharger_sysprop",
+ "libhealthd_draw",
+ "libhealthloop",
+ "libminui",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libpng",
+ "libsuspend",
+ "libutils",
+ ],
+
+ header_libs: [
+ "libhealthd_headers",
+ ],
+
+ srcs: [
+ "healthd_mode_charger.cpp",
+ "AnimationParser.cpp",
+ ],
+
+ target: {
+ vendor: {
+ exclude_static_libs: [
+ "libcharger_sysprop",
+ ],
+ },
+ },
+}
+
+cc_library_headers {
+ name: "libhealthd_headers",
+ vendor_available: true,
+ recovery_available: true,
+ export_include_dirs: ["include"],
+ header_libs: ["libbatteryservice_headers"],
+ export_header_lib_headers: ["libbatteryservice_headers"],
+}
+
+cc_library_static {
+ name: "libbatterymonitor",
+ defaults: ["libbatterymonitor_defaults"],
+ srcs: ["BatteryMonitor.cpp"],
+ static_libs: [
+ "android.hardware.health-V2-ndk",
],
whole_static_libs: [
// Need to translate HIDL to AIDL to support legacy APIs in
// BatteryMonitor.
"android.hardware.health-translate-ndk",
],
- header_libs: ["libhealthd_headers"],
- export_header_lib_headers: ["libhealthd_headers"],
+}
+
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+ name: "libbatterymonitor-V1",
+ defaults: ["libbatterymonitor_defaults"],
+ srcs: ["BatteryMonitor_v1.cpp"],
+ static_libs: [
+ "android.hardware.health-V1-ndk",
+ ],
+ whole_static_libs: [
+ // Need to translate HIDL to AIDL to support legacy APIs in
+ // BatteryMonitor.
+ "android.hardware.health-translate-V1-ndk",
+ ],
}
cc_defaults {
@@ -136,50 +200,31 @@
cc_library_static {
name: "libhealthd_charger_ui",
- vendor_available: true,
- export_include_dirs: [
- "include",
- "include_charger",
+ defaults: ["libhealthd_charger_ui_defaults"],
+
+ static_libs: [
+ "android.hardware.health-V2-ndk",
+ "android.hardware.health-translate-ndk",
],
+ export_static_lib_headers: [
+ "android.hardware.health-V2-ndk",
+ ],
+}
+
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+ name: "libhealthd_charger_ui-V1",
+ defaults: ["libhealthd_charger_ui_defaults"],
+
static_libs: [
"android.hardware.health-V1-ndk",
- "android.hardware.health-translate-ndk",
- "libcharger_sysprop",
- "libhealthd_draw",
- "libhealthloop",
- "libminui",
- ],
-
- shared_libs: [
- "libbase",
- "libcutils",
- "liblog",
- "libpng",
- "libsuspend",
- "libutils",
- ],
-
- header_libs: [
- "libhealthd_headers",
+ "android.hardware.health-translate-V1-ndk",
],
export_static_lib_headers: [
"android.hardware.health-V1-ndk",
],
-
- srcs: [
- "healthd_mode_charger.cpp",
- "AnimationParser.cpp",
- ],
-
- target: {
- vendor: {
- exclude_static_libs: [
- "libcharger_sysprop",
- ],
- },
- },
}
cc_library_static {
@@ -235,7 +280,7 @@
static_libs: [
// common
"android.hardware.health@1.0-convert",
- "android.hardware.health-V1-ndk",
+ "android.hardware.health-V2-ndk",
"libbatterymonitor",
"libcharger_sysprop",
"libhealthd_charger_nops",
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index a7571a2..bd7955a 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -55,7 +55,10 @@
using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
using aidl::android::hardware::health::BatteryCapacityLevel;
+using aidl::android::hardware::health::BatteryChargingPolicy;
+using aidl::android::hardware::health::BatteryChargingState;
using aidl::android::hardware::health::BatteryHealth;
+using aidl::android::hardware::health::BatteryHealthData;
using aidl::android::hardware::health::BatteryStatus;
using aidl::android::hardware::health::HealthInfo;
@@ -135,6 +138,7 @@
mBatteryDevicePresent(false),
mBatteryFixedCapacity(0),
mBatteryFixedTemperature(0),
+ mBatteryHealthStatus(BatteryMonitor::BH_UNKNOWN),
mHealthInfo(std::make_unique<HealthInfo>()) {
initHealthInfo(mHealthInfo.get());
}
@@ -227,6 +231,58 @@
return *ret;
}
+BatteryHealth getBatteryHealthStatus(int status) {
+ BatteryHealth value;
+
+ if (status == BatteryMonitor::BH_NOMINAL)
+ value = BatteryHealth::GOOD;
+ else if (status == BatteryMonitor::BH_MARGINAL)
+ value = BatteryHealth::FAIR;
+ else if (status == BatteryMonitor::BH_NEEDS_REPLACEMENT)
+ value = BatteryHealth::DEAD;
+ else if (status == BatteryMonitor::BH_FAILED)
+ value = BatteryHealth::UNSPECIFIED_FAILURE;
+ else if (status == BatteryMonitor::BH_NOT_AVAILABLE)
+ value = BatteryHealth::NOT_AVAILABLE;
+ else if (status == BatteryMonitor::BH_INCONSISTENT)
+ value = BatteryHealth::INCONSISTENT;
+ else
+ value = BatteryHealth::UNKNOWN;
+
+ return value;
+}
+
+BatteryChargingPolicy getBatteryChargingPolicy(const char* chargingPolicy) {
+ static SysfsStringEnumMap<BatteryChargingPolicy> batteryChargingPolicyMap[] = {
+ {"0", BatteryChargingPolicy::INVALID}, {"1", BatteryChargingPolicy::DEFAULT},
+ {"2", BatteryChargingPolicy::LONG_LIFE}, {"3", BatteryChargingPolicy::ADAPTIVE},
+ {NULL, BatteryChargingPolicy::DEFAULT},
+ };
+
+ auto ret = mapSysfsString(chargingPolicy, batteryChargingPolicyMap);
+ if (!ret) {
+ *ret = BatteryChargingPolicy::DEFAULT;
+ }
+
+ return *ret;
+}
+
+BatteryChargingState getBatteryChargingState(const char* chargingState) {
+ static SysfsStringEnumMap<BatteryChargingState> batteryChargingStateMap[] = {
+ {"0", BatteryChargingState::INVALID}, {"1", BatteryChargingState::NORMAL},
+ {"2", BatteryChargingState::TOO_COLD}, {"3", BatteryChargingState::TOO_HOT},
+ {"4", BatteryChargingState::LONG_LIFE}, {"5", BatteryChargingState::ADAPTIVE},
+ {NULL, BatteryChargingState::NORMAL},
+ };
+
+ auto ret = mapSysfsString(chargingState, batteryChargingStateMap);
+ if (!ret) {
+ *ret = BatteryChargingState::NORMAL;
+ }
+
+ return *ret;
+}
+
static int readFromFile(const String8& path, std::string* buf) {
buf->clear();
if (android::base::ReadFileToString(path.c_str(), buf)) {
@@ -235,6 +291,10 @@
return buf->length();
}
+static bool writeToFile(const String8& path, int32_t in_value) {
+ return android::base::WriteStringToFile(std::to_string(in_value), path.c_str());
+}
+
static BatteryMonitor::PowerSupplyType readPowerSupplyType(const String8& path) {
static SysfsStringEnumMap<int> supplyTypeMap[] = {
{"Unknown", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
@@ -336,6 +396,21 @@
mHealthInfo->batteryFullChargeDesignCapacityUah =
getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
+ if (!mHealthdConfig->batteryHealthStatusPath.isEmpty())
+ mBatteryHealthStatus = getIntField(mHealthdConfig->batteryHealthStatusPath);
+
+ if (!mHealthdConfig->batteryStateOfHealthPath.isEmpty())
+ mHealthInfo->batteryHealthData->batteryStateOfHealth =
+ getIntField(mHealthdConfig->batteryStateOfHealthPath);
+
+ if (!mHealthdConfig->batteryManufacturingDatePath.isEmpty())
+ mHealthInfo->batteryHealthData->batteryManufacturingDateSeconds =
+ getIntField(mHealthdConfig->batteryManufacturingDatePath);
+
+ if (!mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
+ mHealthInfo->batteryHealthData->batteryFirstUsageSeconds =
+ getIntField(mHealthdConfig->batteryFirstUsageDatePath);
+
mHealthInfo->batteryTemperatureTenthsCelsius =
mBatteryFixedTemperature ? mBatteryFixedTemperature
: getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -348,12 +423,23 @@
if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
- if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
- mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
+ // Backward compatible with android.hardware.health V1
+ if (mBatteryHealthStatus < BatteryMonitor::BH_MARGINAL) {
+ if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
+ mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
+ } else {
+ mHealthInfo->batteryHealth = getBatteryHealthStatus(mBatteryHealthStatus);
+ }
if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
mHealthInfo->batteryTechnology = String8(buf.c_str());
+ if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
+ mHealthInfo->chargingPolicy = getBatteryChargingPolicy(buf.c_str());
+
+ if (readFromFile(mHealthdConfig->chargingStatePath, &buf) > 0)
+ mHealthInfo->chargingState = getBatteryChargingState(buf.c_str());
+
double MaxPower = 0;
for (size_t i = 0; i < mChargerNames.size(); i++) {
@@ -476,6 +562,47 @@
return static_cast<int>(result);
}
+status_t BatteryMonitor::setChargingPolicy(int value) {
+ status_t ret = NAME_NOT_FOUND;
+ bool result;
+ if (!mHealthdConfig->chargingPolicyPath.isEmpty()) {
+ result = writeToFile(mHealthdConfig->chargingPolicyPath, value);
+ if (!result) {
+ KLOG_WARNING(LOG_TAG, "setChargingPolicy fail\n");
+ ret = BAD_VALUE;
+ } else {
+ ret = OK;
+ }
+ }
+ return ret;
+}
+
+int BatteryMonitor::getChargingPolicy() {
+ BatteryChargingPolicy result = BatteryChargingPolicy::DEFAULT;
+ if (!mHealthdConfig->chargingPolicyPath.isEmpty()) {
+ std::string buf;
+ if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
+ result = getBatteryChargingPolicy(buf.c_str());
+ }
+ return static_cast<int>(result);
+}
+
+int BatteryMonitor::getBatteryHealthData(int id) {
+ if (id == BATTERY_PROP_MANUFACTURING_DATE) {
+ if (!mHealthdConfig->batteryManufacturingDatePath.isEmpty())
+ return getIntField(mHealthdConfig->batteryManufacturingDatePath);
+ }
+ if (id == BATTERY_PROP_FIRST_USAGE_DATE) {
+ if (!mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
+ return getIntField(mHealthdConfig->batteryFirstUsageDatePath);
+ }
+ if (id == BATTERY_PROP_STATE_OF_HEALTH) {
+ if (!mHealthdConfig->batteryStateOfHealthPath.isEmpty())
+ return getIntField(mHealthdConfig->batteryStateOfHealthPath);
+ }
+ return 0;
+}
+
status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
status_t ret = BAD_VALUE;
std::string buf;
@@ -536,6 +663,26 @@
ret = OK;
break;
+ case BATTERY_PROP_CHARGING_POLICY:
+ val->valueInt64 = getChargingPolicy();
+ ret = OK;
+ break;
+
+ case BATTERY_PROP_MANUFACTURING_DATE:
+ val->valueInt64 = getBatteryHealthData(BATTERY_PROP_MANUFACTURING_DATE);
+ ret = OK;
+ break;
+
+ case BATTERY_PROP_FIRST_USAGE_DATE:
+ val->valueInt64 = getBatteryHealthData(BATTERY_PROP_FIRST_USAGE_DATE);
+ ret = OK;
+ break;
+
+ case BATTERY_PROP_STATE_OF_HEALTH:
+ val->valueInt64 = getBatteryHealthData(BATTERY_PROP_STATE_OF_HEALTH);
+ ret = OK;
+ break;
+
default:
break;
}
@@ -758,6 +905,50 @@
mHealthdConfig->batteryTechnologyPath = path;
}
+ if (mHealthdConfig->batteryStateOfHealthPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/state_of_health", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) {
+ mHealthdConfig->batteryStateOfHealthPath = path;
+ } else {
+ path.clear();
+ path.appendFormat("%s/%s/health_index", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryStateOfHealthPath = path;
+ }
+ }
+
+ if (mHealthdConfig->batteryHealthStatusPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/health_status", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) mHealthdConfig->batteryHealthStatusPath = path;
+ }
+
+ if (mHealthdConfig->batteryManufacturingDatePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/manufacturing_date", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryManufacturingDatePath = path;
+ }
+
+ if (mHealthdConfig->batteryFirstUsageDatePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/first_usage_date", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) mHealthdConfig->batteryFirstUsageDatePath = path;
+ }
+
+ if (mHealthdConfig->chargingStatePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charging_state", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) mHealthdConfig->chargingStatePath = path;
+ }
+
+ if (mHealthdConfig->chargingPolicyPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charging_policy", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) mHealthdConfig->chargingPolicyPath = path;
+ }
+
break;
case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
@@ -810,6 +1001,18 @@
KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
+ if (mHealthdConfig->batteryStateOfHealthPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryStateOfHealthPath not found\n");
+ if (mHealthdConfig->batteryHealthStatusPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryHealthStatusPath not found\n");
+ if (mHealthdConfig->batteryManufacturingDatePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryManufacturingDatePath not found\n");
+ if (mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryFirstUsageDatePath not found\n");
+ if (mHealthdConfig->chargingStatePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "chargingStatePath not found\n");
+ if (mHealthdConfig->chargingPolicyPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "chargingPolicyPath not found\n");
}
if (property_get("ro.boot.fake_battery", pval, NULL) > 0
diff --git a/healthd/BatteryMonitor_v1.cpp b/healthd/BatteryMonitor_v1.cpp
new file mode 100644
index 0000000..b87c493
--- /dev/null
+++ b/healthd/BatteryMonitor_v1.cpp
@@ -0,0 +1,822 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "healthd"
+
+#include <healthd/healthd.h>
+#include <healthd/BatteryMonitor_v1.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <memory>
+#include <optional>
+
+#include <aidl/android/hardware/health/HealthInfo.h>
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <android/hardware/health/2.1/types.h>
+#include <android/hardware/health/translate-ndk.h>
+#include <batteryservice/BatteryService.h>
+#include <cutils/klog.h>
+#include <cutils/properties.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#define POWER_SUPPLY_SUBSYSTEM "power_supply"
+#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
+#define FAKE_BATTERY_CAPACITY 42
+#define FAKE_BATTERY_TEMPERATURE 424
+#define MILLION 1.0e6
+#define DEFAULT_VBUS_VOLTAGE 5000000
+
+using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
+using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
+using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
+using aidl::android::hardware::health::BatteryCapacityLevel;
+using aidl::android::hardware::health::BatteryHealth;
+using aidl::android::hardware::health::BatteryStatus;
+using aidl::android::hardware::health::HealthInfo;
+
+namespace {
+
+// Translate from AIDL back to HIDL definition for getHealthInfo_*_* calls.
+// Skips storageInfo and diskStats.
+void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
+ ::android::hardware::health::V1_0::HealthInfo* out) {
+ out->chargerAcOnline = in.chargerAcOnline;
+ out->chargerUsbOnline = in.chargerUsbOnline;
+ out->chargerWirelessOnline = in.chargerWirelessOnline;
+ out->maxChargingCurrent = in.maxChargingCurrentMicroamps;
+ out->maxChargingVoltage = in.maxChargingVoltageMicrovolts;
+ out->batteryStatus =
+ static_cast<::android::hardware::health::V1_0::BatteryStatus>(in.batteryStatus);
+ out->batteryHealth =
+ static_cast<::android::hardware::health::V1_0::BatteryHealth>(in.batteryHealth);
+ out->batteryPresent = in.batteryPresent;
+ out->batteryLevel = in.batteryLevel;
+ out->batteryVoltage = in.batteryVoltageMillivolts;
+ out->batteryTemperature = in.batteryTemperatureTenthsCelsius;
+ out->batteryCurrent = in.batteryCurrentMicroamps;
+ out->batteryCycleCount = in.batteryCycleCount;
+ out->batteryFullCharge = in.batteryFullChargeUah;
+ out->batteryChargeCounter = in.batteryChargeCounterUah;
+ out->batteryTechnology = in.batteryTechnology;
+}
+
+void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
+ ::android::hardware::health::V2_0::HealthInfo* out) {
+ translateToHidl(in, &out->legacy);
+ out->batteryCurrentAverage = in.batteryCurrentAverageMicroamps;
+ // Skip storageInfo and diskStats
+}
+
+void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
+ ::android::hardware::health::V2_1::HealthInfo* out) {
+ translateToHidl(in, &out->legacy);
+ out->batteryCapacityLevel = static_cast<android::hardware::health::V2_1::BatteryCapacityLevel>(
+ in.batteryCapacityLevel);
+ out->batteryChargeTimeToFullNowSeconds = in.batteryChargeTimeToFullNowSeconds;
+ out->batteryFullChargeDesignCapacityUah = in.batteryFullChargeDesignCapacityUah;
+}
+
+} // namespace
+
+namespace android {
+
+template <typename T>
+struct SysfsStringEnumMap {
+ const char* s;
+ T val;
+};
+
+template <typename T>
+static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
+ for (int i = 0; map[i].s; i++)
+ if (!strcmp(str, map[i].s))
+ return map[i].val;
+
+ return std::nullopt;
+}
+
+static void initHealthInfo(HealthInfo* health_info) {
+ *health_info = {
+ .batteryCapacityLevel = BatteryCapacityLevel::UNSUPPORTED,
+ .batteryChargeTimeToFullNowSeconds =
+ (int64_t)HealthInfo::BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED,
+ .batteryStatus = BatteryStatus::UNKNOWN,
+ .batteryHealth = BatteryHealth::UNKNOWN,
+ };
+}
+
+BatteryMonitor::BatteryMonitor()
+ : mHealthdConfig(nullptr),
+ mBatteryDevicePresent(false),
+ mBatteryFixedCapacity(0),
+ mBatteryFixedTemperature(0),
+ mHealthInfo(std::make_unique<HealthInfo>()) {
+ initHealthInfo(mHealthInfo.get());
+}
+
+BatteryMonitor::~BatteryMonitor() {}
+
+HealthInfo_1_0 BatteryMonitor::getHealthInfo_1_0() const {
+ HealthInfo_1_0 health_info_1_0;
+ translateToHidl(*mHealthInfo, &health_info_1_0);
+ return health_info_1_0;
+}
+
+HealthInfo_2_0 BatteryMonitor::getHealthInfo_2_0() const {
+ HealthInfo_2_0 health_info_2_0;
+ translateToHidl(*mHealthInfo, &health_info_2_0);
+ return health_info_2_0;
+}
+
+HealthInfo_2_1 BatteryMonitor::getHealthInfo_2_1() const {
+ HealthInfo_2_1 health_info_2_1;
+ translateToHidl(*mHealthInfo, &health_info_2_1);
+ return health_info_2_1;
+}
+
+const HealthInfo& BatteryMonitor::getHealthInfo() const {
+ return *mHealthInfo;
+}
+
+BatteryStatus getBatteryStatus(const char* status) {
+ static SysfsStringEnumMap<BatteryStatus> batteryStatusMap[] = {
+ {"Unknown", BatteryStatus::UNKNOWN},
+ {"Charging", BatteryStatus::CHARGING},
+ {"Discharging", BatteryStatus::DISCHARGING},
+ {"Not charging", BatteryStatus::NOT_CHARGING},
+ {"Full", BatteryStatus::FULL},
+ {NULL, BatteryStatus::UNKNOWN},
+ };
+
+ auto ret = mapSysfsString(status, batteryStatusMap);
+ if (!ret) {
+ KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
+ *ret = BatteryStatus::UNKNOWN;
+ }
+
+ return *ret;
+}
+
+BatteryCapacityLevel getBatteryCapacityLevel(const char* capacityLevel) {
+ static SysfsStringEnumMap<BatteryCapacityLevel> batteryCapacityLevelMap[] = {
+ {"Unknown", BatteryCapacityLevel::UNKNOWN},
+ {"Critical", BatteryCapacityLevel::CRITICAL},
+ {"Low", BatteryCapacityLevel::LOW},
+ {"Normal", BatteryCapacityLevel::NORMAL},
+ {"High", BatteryCapacityLevel::HIGH},
+ {"Full", BatteryCapacityLevel::FULL},
+ {NULL, BatteryCapacityLevel::UNSUPPORTED},
+ };
+
+ auto ret = mapSysfsString(capacityLevel, batteryCapacityLevelMap);
+ if (!ret) {
+ KLOG_WARNING(LOG_TAG, "Unsupported battery capacity level '%s'\n", capacityLevel);
+ *ret = BatteryCapacityLevel::UNSUPPORTED;
+ }
+
+ return *ret;
+}
+
+BatteryHealth getBatteryHealth(const char* status) {
+ static SysfsStringEnumMap<BatteryHealth> batteryHealthMap[] = {
+ {"Unknown", BatteryHealth::UNKNOWN},
+ {"Good", BatteryHealth::GOOD},
+ {"Overheat", BatteryHealth::OVERHEAT},
+ {"Dead", BatteryHealth::DEAD},
+ {"Over voltage", BatteryHealth::OVER_VOLTAGE},
+ {"Unspecified failure", BatteryHealth::UNSPECIFIED_FAILURE},
+ {"Cold", BatteryHealth::COLD},
+ // battery health values from JEITA spec
+ {"Warm", BatteryHealth::GOOD},
+ {"Cool", BatteryHealth::GOOD},
+ {"Hot", BatteryHealth::OVERHEAT},
+ {NULL, BatteryHealth::UNKNOWN},
+ };
+
+ auto ret = mapSysfsString(status, batteryHealthMap);
+ if (!ret) {
+ KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
+ *ret = BatteryHealth::UNKNOWN;
+ }
+
+ return *ret;
+}
+
+static int readFromFile(const String8& path, std::string* buf) {
+ buf->clear();
+ if (android::base::ReadFileToString(path.c_str(), buf)) {
+ *buf = android::base::Trim(*buf);
+ }
+ return buf->length();
+}
+
+static BatteryMonitor::PowerSupplyType readPowerSupplyType(const String8& path) {
+ static SysfsStringEnumMap<int> supplyTypeMap[] = {
+ {"Unknown", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
+ {"Battery", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_BATTERY},
+ {"UPS", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"Mains", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
+ {"USB_DCP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_HVDCP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_CDP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_ACA", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_C", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_PD", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
+ {"USB_PD_DRP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
+ {"Wireless", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
+ {"Dock", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_DOCK},
+ {NULL, 0},
+ };
+ std::string buf;
+
+ if (readFromFile(path, &buf) <= 0) {
+ return BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+ }
+
+ auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
+ if (!ret) {
+ KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
+ *ret = BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+ }
+
+ return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
+}
+
+static bool getBooleanField(const String8& path) {
+ std::string buf;
+ bool value = false;
+
+ if (readFromFile(path, &buf) > 0)
+ if (buf[0] != '0')
+ value = true;
+
+ return value;
+}
+
+static int getIntField(const String8& path) {
+ std::string buf;
+ int value = 0;
+
+ if (readFromFile(path, &buf) > 0)
+ android::base::ParseInt(buf, &value);
+
+ return value;
+}
+
+static bool isScopedPowerSupply(const char* name) {
+ constexpr char kScopeDevice[] = "Device";
+
+ String8 path;
+ path.appendFormat("%s/%s/scope", POWER_SUPPLY_SYSFS_PATH, name);
+ std::string scope;
+ return (readFromFile(path, &scope) > 0 && scope == kScopeDevice);
+}
+
+void BatteryMonitor::updateValues(void) {
+ initHealthInfo(mHealthInfo.get());
+
+ if (!mHealthdConfig->batteryPresentPath.isEmpty())
+ mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
+ else
+ mHealthInfo->batteryPresent = mBatteryDevicePresent;
+
+ mHealthInfo->batteryLevel = mBatteryFixedCapacity
+ ? mBatteryFixedCapacity
+ : getIntField(mHealthdConfig->batteryCapacityPath);
+ mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
+
+ if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
+ mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
+
+ if (!mHealthdConfig->batteryFullChargePath.isEmpty())
+ mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
+
+ if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
+ mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
+
+ if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
+ mHealthInfo->batteryChargeCounterUah =
+ getIntField(mHealthdConfig->batteryChargeCounterPath);
+
+ if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
+ mHealthInfo->batteryCurrentAverageMicroamps =
+ getIntField(mHealthdConfig->batteryCurrentAvgPath);
+
+ if (!mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
+ mHealthInfo->batteryChargeTimeToFullNowSeconds =
+ getIntField(mHealthdConfig->batteryChargeTimeToFullNowPath);
+
+ if (!mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
+ mHealthInfo->batteryFullChargeDesignCapacityUah =
+ getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
+
+ mHealthInfo->batteryTemperatureTenthsCelsius =
+ mBatteryFixedTemperature ? mBatteryFixedTemperature
+ : getIntField(mHealthdConfig->batteryTemperaturePath);
+
+ std::string buf;
+
+ if (readFromFile(mHealthdConfig->batteryCapacityLevelPath, &buf) > 0)
+ mHealthInfo->batteryCapacityLevel = getBatteryCapacityLevel(buf.c_str());
+
+ if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
+ mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
+
+ if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
+ mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
+
+ if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
+ mHealthInfo->batteryTechnology = String8(buf.c_str());
+
+ double MaxPower = 0;
+
+ for (size_t i = 0; i < mChargerNames.size(); i++) {
+ String8 path;
+ path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+ if (getIntField(path)) {
+ path.clear();
+ path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+ switch(readPowerSupplyType(path)) {
+ case ANDROID_POWER_SUPPLY_TYPE_AC:
+ mHealthInfo->chargerAcOnline = true;
+ break;
+ case ANDROID_POWER_SUPPLY_TYPE_USB:
+ mHealthInfo->chargerUsbOnline = true;
+ break;
+ case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+ mHealthInfo->chargerWirelessOnline = true;
+ break;
+ case ANDROID_POWER_SUPPLY_TYPE_DOCK:
+ mHealthInfo->chargerDockOnline = true;
+ break;
+ default:
+ path.clear();
+ path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+ if (access(path.string(), R_OK) == 0)
+ mHealthInfo->chargerDockOnline = true;
+ else
+ KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
+ mChargerNames[i].string());
+ }
+ path.clear();
+ path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+ int ChargingCurrent =
+ (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
+
+ path.clear();
+ path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+
+ int ChargingVoltage =
+ (access(path.string(), R_OK) == 0) ? getIntField(path) :
+ DEFAULT_VBUS_VOLTAGE;
+
+ double power = ((double)ChargingCurrent / MILLION) *
+ ((double)ChargingVoltage / MILLION);
+ if (MaxPower < power) {
+ mHealthInfo->maxChargingCurrentMicroamps = ChargingCurrent;
+ mHealthInfo->maxChargingVoltageMicrovolts = ChargingVoltage;
+ MaxPower = power;
+ }
+ }
+ }
+}
+
+static void doLogValues(const HealthInfo& props, const struct healthd_config& healthd_config) {
+ char dmesgline[256];
+ size_t len;
+ if (props.batteryPresent) {
+ snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
+ props.batteryLevel, props.batteryVoltageMillivolts,
+ props.batteryTemperatureTenthsCelsius < 0 ? "-" : "",
+ abs(props.batteryTemperatureTenthsCelsius / 10),
+ abs(props.batteryTemperatureTenthsCelsius % 10), props.batteryHealth,
+ props.batteryStatus);
+
+ len = strlen(dmesgline);
+ if (!healthd_config.batteryCurrentNowPath.isEmpty()) {
+ len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
+ props.batteryCurrentMicroamps);
+ }
+
+ if (!healthd_config.batteryFullChargePath.isEmpty()) {
+ len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
+ props.batteryFullChargeUah);
+ }
+
+ if (!healthd_config.batteryCycleCountPath.isEmpty()) {
+ len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
+ props.batteryCycleCount);
+ }
+ } else {
+ len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
+ }
+
+ snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s%s",
+ props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
+ props.chargerWirelessOnline ? "w" : "", props.chargerDockOnline ? "d" : "");
+
+ KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
+}
+
+void BatteryMonitor::logValues(const HealthInfo_2_1& health_info,
+ const struct healthd_config& healthd_config) {
+ HealthInfo aidl_health_info;
+ (void)android::h2a::translate(health_info, &aidl_health_info);
+ doLogValues(aidl_health_info, healthd_config);
+}
+
+void BatteryMonitor::logValues(void) {
+ doLogValues(*mHealthInfo, *mHealthdConfig);
+}
+
+bool BatteryMonitor::isChargerOnline() {
+ const HealthInfo& props = *mHealthInfo;
+ return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline |
+ props.chargerDockOnline;
+}
+
+int BatteryMonitor::getChargeStatus() {
+ BatteryStatus result = BatteryStatus::UNKNOWN;
+ if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
+ std::string buf;
+ if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
+ result = getBatteryStatus(buf.c_str());
+ }
+ return static_cast<int>(result);
+}
+
+status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
+ status_t ret = BAD_VALUE;
+ std::string buf;
+
+ val->valueInt64 = LONG_MIN;
+
+ switch(id) {
+ case BATTERY_PROP_CHARGE_COUNTER:
+ if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->batteryChargeCounterPath);
+ ret = OK;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_CURRENT_NOW:
+ if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->batteryCurrentNowPath);
+ ret = OK;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_CURRENT_AVG:
+ if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->batteryCurrentAvgPath);
+ ret = OK;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_CAPACITY:
+ if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->batteryCapacityPath);
+ ret = OK;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_ENERGY_COUNTER:
+ if (mHealthdConfig->energyCounter) {
+ ret = mHealthdConfig->energyCounter(&val->valueInt64);
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_BATTERY_STATUS:
+ val->valueInt64 = getChargeStatus();
+ ret = OK;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+void BatteryMonitor::dumpState(int fd) {
+ int v;
+ char vs[128];
+ const HealthInfo& props = *mHealthInfo;
+
+ snprintf(vs, sizeof(vs),
+ "ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
+ props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
+ props.chargerDockOnline, props.maxChargingCurrentMicroamps,
+ props.maxChargingVoltageMicrovolts);
+ write(fd, vs, strlen(vs));
+ snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
+ props.batteryStatus, props.batteryHealth, props.batteryPresent);
+ write(fd, vs, strlen(vs));
+ snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", props.batteryLevel,
+ props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
+ write(fd, vs, strlen(vs));
+
+ if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+ v = getIntField(mHealthdConfig->batteryCurrentNowPath);
+ snprintf(vs, sizeof(vs), "current now: %d\n", v);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
+ v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
+ snprintf(vs, sizeof(vs), "current avg: %d\n", v);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+ v = getIntField(mHealthdConfig->batteryChargeCounterPath);
+ snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+ snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrentMicroamps);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+ snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+ snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullChargeUah);
+ write(fd, vs, strlen(vs));
+ }
+}
+
+void BatteryMonitor::init(struct healthd_config *hc) {
+ String8 path;
+ char pval[PROPERTY_VALUE_MAX];
+
+ mHealthdConfig = hc;
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
+ if (dir == NULL) {
+ KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
+ } else {
+ struct dirent* entry;
+
+ while ((entry = readdir(dir.get()))) {
+ const char* name = entry->d_name;
+
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+
+ std::vector<String8>::iterator itIgnoreName =
+ find(hc->ignorePowerSupplyNames.begin(), hc->ignorePowerSupplyNames.end(),
+ String8(name));
+ if (itIgnoreName != hc->ignorePowerSupplyNames.end())
+ continue;
+
+ // Look for "type" file in each subdirectory
+ path.clear();
+ path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
+ switch(readPowerSupplyType(path)) {
+ case ANDROID_POWER_SUPPLY_TYPE_AC:
+ case ANDROID_POWER_SUPPLY_TYPE_USB:
+ case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+ case ANDROID_POWER_SUPPLY_TYPE_DOCK:
+ path.clear();
+ path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path.string(), R_OK) == 0)
+ mChargerNames.add(String8(name));
+ break;
+
+ case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
+ // Some devices expose the battery status of sub-component like
+ // stylus. Such a device-scoped battery info needs to be skipped
+ // in BatteryMonitor, which is intended to report the status of
+ // the battery supplying the power to the whole system.
+ if (isScopedPowerSupply(name)) continue;
+ mBatteryDevicePresent = true;
+
+ if (mHealthdConfig->batteryStatusPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryStatusPath = path;
+ }
+
+ if (mHealthdConfig->batteryHealthPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryHealthPath = path;
+ }
+
+ if (mHealthdConfig->batteryPresentPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryPresentPath = path;
+ }
+
+ if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryCapacityPath = path;
+ }
+
+ if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/voltage_now",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) {
+ mHealthdConfig->batteryVoltagePath = path;
+ }
+ }
+
+ if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charge_full",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryFullChargePath = path;
+ }
+
+ if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/current_now",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryCurrentNowPath = path;
+ }
+
+ if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/cycle_count",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryCycleCountPath = path;
+ }
+
+ if (mHealthdConfig->batteryCapacityLevelPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/capacity_level", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) mHealthdConfig->batteryCapacityLevelPath = path;
+ }
+
+ if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/time_to_full_now", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryChargeTimeToFullNowPath = path;
+ }
+
+ if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charge_full_design", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryFullChargeDesignCapacityUahPath = path;
+ }
+
+ if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/current_avg",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryCurrentAvgPath = path;
+ }
+
+ if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charge_counter",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryChargeCounterPath = path;
+ }
+
+ if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0) {
+ mHealthdConfig->batteryTemperaturePath = path;
+ }
+ }
+
+ if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/technology",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryTechnologyPath = path;
+ }
+
+ break;
+
+ case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
+ break;
+ }
+
+ // Look for "is_dock" file
+ path.clear();
+ path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path.string(), R_OK) == 0) {
+ path.clear();
+ path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path.string(), R_OK) == 0)
+ mChargerNames.add(String8(name));
+
+ }
+ }
+ }
+
+ // Typically the case for devices which do not have a battery and
+ // and are always plugged into AC mains.
+ if (!mBatteryDevicePresent) {
+ KLOG_WARNING(LOG_TAG, "No battery devices found\n");
+ hc->periodic_chores_interval_fast = -1;
+ hc->periodic_chores_interval_slow = -1;
+ } else {
+ if (mHealthdConfig->batteryStatusPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
+ if (mHealthdConfig->batteryHealthPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
+ if (mHealthdConfig->batteryPresentPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
+ if (mHealthdConfig->batteryCapacityPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
+ if (mHealthdConfig->batteryVoltagePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
+ if (mHealthdConfig->batteryTemperaturePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
+ if (mHealthdConfig->batteryTechnologyPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
+ if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
+ if (mHealthdConfig->batteryFullChargePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
+ if (mHealthdConfig->batteryCycleCountPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
+ if (mHealthdConfig->batteryCapacityLevelPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryCapacityLevelPath not found\n");
+ if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
+ if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
+ }
+
+ if (property_get("ro.boot.fake_battery", pval, NULL) > 0
+ && strtol(pval, NULL, 10) != 0) {
+ mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
+ mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
+ }
+}
+
+}; // namespace android
diff --git a/healthd/healthd.rc b/healthd/healthd.rc
deleted file mode 100644
index 8e2ebb6..0000000
--- a/healthd/healthd.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service healthd /system/bin/healthd
- class hal
- critical
- group root system wakelock
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 1ce174b..26af13b 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -88,7 +88,7 @@
#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
#define UNPLUGGED_DISPLAY_TIME (3 * MSEC_PER_SEC)
-#define MAX_BATT_LEVEL_WAIT_TIME (3 * MSEC_PER_SEC)
+#define MAX_BATT_LEVEL_WAIT_TIME (5 * MSEC_PER_SEC)
#define UNPLUGGED_SHUTDOWN_TIME_PROP "ro.product.charger.unplugged_shutdown_time"
#define LAST_KMSG_MAX_SZ (32 * 1024)
@@ -620,6 +620,18 @@
kick_animation(&batt_anim_);
}
health_info_ = health_info;
+
+ if (property_get_bool("ro.charger_mode_autoboot", false)) {
+ if (health_info_.battery_level >= boot_min_cap_) {
+ if (property_get_bool("ro.enable_boot_charger_mode", false)) {
+ LOGW("booting from charger mode\n");
+ property_set("sys.boot_from_charger_mode", "1");
+ } else {
+ LOGW("Battery SOC = %d%%, Automatically rebooting\n", health_info_.battery_level);
+ reboot(RB_AUTOBOOT);
+ }
+ }
+ }
}
int Charger::OnPrepareToWait(void) {
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 8cbf5ea..e9998ba 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -56,6 +56,16 @@
ANDROID_POWER_SUPPLY_TYPE_DOCK
};
+ enum BatteryHealthStatus {
+ BH_UNKNOWN = -1,
+ BH_NOMINAL,
+ BH_MARGINAL,
+ BH_NEEDS_REPLACEMENT,
+ BH_FAILED,
+ BH_NOT_AVAILABLE,
+ BH_INCONSISTENT,
+ };
+
BatteryMonitor();
~BatteryMonitor();
void init(struct healthd_config *hc);
@@ -72,6 +82,10 @@
void logValues(void);
bool isChargerOnline();
+ int setChargingPolicy(int value);
+ int getChargingPolicy();
+ int getBatteryHealthData(int id);
+
static void logValues(const android::hardware::health::V2_1::HealthInfo& health_info,
const struct healthd_config& healthd_config);
@@ -81,6 +95,7 @@
bool mBatteryDevicePresent;
int mBatteryFixedCapacity;
int mBatteryFixedTemperature;
+ int mBatteryHealthStatus;
std::unique_ptr<aidl::android::hardware::health::HealthInfo> mHealthInfo;
};
diff --git a/healthd/include/healthd/BatteryMonitor_v1.h b/healthd/include/healthd/BatteryMonitor_v1.h
new file mode 100644
index 0000000..49f6f9d
--- /dev/null
+++ b/healthd/include/healthd/BatteryMonitor_v1.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 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 HEALTHD_BATTERYMONITOR_V1_H
+#define HEALTHD_BATTERYMONITOR_V1_H
+
+#include <memory>
+
+#include <batteryservice/BatteryService.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <healthd/healthd.h>
+
+namespace aidl::android::hardware::health {
+class HealthInfo;
+} // namespace aidl::android::hardware::health
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+struct HealthInfo;
+} // namespace V1_0
+namespace V2_0 {
+struct HealthInfo;
+} // namespace V2_0
+namespace V2_1 {
+struct HealthInfo;
+} // namespace V2_1
+} // namespace health
+} // namespace hardware
+
+class BatteryMonitor {
+ public:
+
+ enum PowerSupplyType {
+ ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
+ ANDROID_POWER_SUPPLY_TYPE_AC,
+ ANDROID_POWER_SUPPLY_TYPE_USB,
+ ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
+ ANDROID_POWER_SUPPLY_TYPE_BATTERY,
+ ANDROID_POWER_SUPPLY_TYPE_DOCK
+ };
+
+ BatteryMonitor();
+ ~BatteryMonitor();
+ void init(struct healthd_config *hc);
+ int getChargeStatus();
+ status_t getProperty(int id, struct BatteryProperty *val);
+ void dumpState(int fd);
+
+ android::hardware::health::V1_0::HealthInfo getHealthInfo_1_0() const;
+ android::hardware::health::V2_0::HealthInfo getHealthInfo_2_0() const;
+ android::hardware::health::V2_1::HealthInfo getHealthInfo_2_1() const;
+ const aidl::android::hardware::health::HealthInfo& getHealthInfo() const;
+
+ void updateValues(void);
+ void logValues(void);
+ bool isChargerOnline();
+
+ static void logValues(const android::hardware::health::V2_1::HealthInfo& health_info,
+ const struct healthd_config& healthd_config);
+
+ private:
+ struct healthd_config *mHealthdConfig;
+ Vector<String8> mChargerNames;
+ bool mBatteryDevicePresent;
+ int mBatteryFixedCapacity;
+ int mBatteryFixedTemperature;
+ std::unique_ptr<aidl::android::hardware::health::HealthInfo> mHealthInfo;
+};
+
+}; // namespace android
+
+#endif // HEALTHD_BATTERYMONITOR_V1_H
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index 706c332..688e458 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -72,6 +72,12 @@
android::String8 batteryCapacityLevelPath;
android::String8 batteryChargeTimeToFullNowPath;
android::String8 batteryFullChargeDesignCapacityUahPath;
+ android::String8 batteryStateOfHealthPath;
+ android::String8 batteryHealthStatusPath;
+ android::String8 batteryManufacturingDatePath;
+ android::String8 batteryFirstUsageDatePath;
+ android::String8 chargingStatePath;
+ android::String8 chargingPolicyPath;
int (*energyCounter)(int64_t *);
int boot_min_cap;
diff --git a/init/Android.bp b/init/Android.bp
index c7e7de8..1af398a 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -169,6 +169,7 @@
"libfsverity_init",
"liblmkd_utils",
"liblz4",
+ "libzstd",
"libmini_keyctl_static",
"libmodprobe",
"libprocinfo",
@@ -213,8 +214,8 @@
visibility: [":__subpackages__"],
}
-cc_library_static {
- name: "libinit",
+cc_defaults {
+ name: "libinit_defaults",
recovery_available: true,
defaults: [
"init_defaults",
@@ -227,7 +228,6 @@
],
whole_static_libs: [
"libcap",
- "libcom.android.sysprop.apex",
"libcom.android.sysprop.init",
],
header_libs: ["bootimg_headers"],
@@ -251,10 +251,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 {
@@ -264,12 +271,11 @@
],
}
-cc_binary {
- name: "init_second_stage",
+cc_defaults {
+ name: "init_second_stage_defaults",
recovery_available: true,
stem: "init",
defaults: ["init_defaults"],
- static_libs: ["libinit"],
srcs: ["main.cpp"],
symlinks: ["ueventd"],
target: {
@@ -303,9 +309,24 @@
],
},
},
+}
+
+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"],
+ static_libs: ["libinit.microdroid"],
+ cflags: ["-DMICRODROID=1"],
+ installable: false,
visibility: ["//packages/modules/Virtualization/microdroid"],
}
+
soong_config_module_type {
name: "init_first_stage_cc_defaults",
module_type: "cc_defaults",
@@ -323,12 +344,8 @@
installable: false,
},
},
-}
-cc_binary {
- name: "init_first_stage",
stem: "init",
- defaults: ["init_first_stage_defaults"],
srcs: [
"block_dev_initializer.cpp",
@@ -370,6 +387,7 @@
"libprotobuf-cpp-lite",
"libsnapshot_cow",
"liblz4",
+ "libzstd",
"libsnapshot_init",
"update_metadata-protos",
"libprocinfo",
@@ -441,6 +459,18 @@
install_in_root: true,
}
+cc_binary {
+ name: "init_first_stage",
+ defaults: ["init_first_stage_defaults"],
+}
+
+cc_binary {
+ name: "init_first_stage.microdroid",
+ defaults: ["init_first_stage_defaults"],
+ cflags: ["-DMICRODROID=1"],
+ installable: false,
+}
+
phony {
name: "init_system",
required: ["init_second_stage"],
@@ -454,15 +484,7 @@
defaults: ["init_defaults"],
require_root: true,
- compile_multilib: "both",
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
+ compile_multilib: "first",
srcs: [
"devices_test.cpp",
@@ -510,11 +532,13 @@
"libbase",
"libcutils",
"libselinux",
- "libhidl-gen-utils",
"liblog",
"libprocessgroup",
"libprotobuf-cpp-lite",
],
+ static_libs: [
+ "libhidl-gen-utils",
+ ],
}
cc_library_static {
diff --git a/init/AndroidTest.xml b/init/AndroidTest.xml
index 6f22ab7..8b05484 100644
--- a/init/AndroidTest.xml
+++ b/init/AndroidTest.xml
@@ -22,7 +22,6 @@
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
<option name="push" value="CtsInitTestCases->/data/local/tmp/CtsInitTestCases" />
- <option name="append-bitness" value="true" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
<option name="throw-on-error" value="false" />
diff --git a/init/OWNERS b/init/OWNERS
index 4604d06..68b9396 100644
--- a/init/OWNERS
+++ b/init/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 1312227
dvander@google.com
jiyong@google.com
diff --git a/init/README.md b/init/README.md
index 6596528..5fced19 100644
--- a/init/README.md
+++ b/init/README.md
@@ -162,6 +162,28 @@
setprop e 1
setprop f 2
+If the property `true` wasn't `true` when the `boot` was triggered, then the
+order of the commands executed will be:
+
+ setprop a 1
+ setprop b 2
+ setprop e 1
+ setprop f 2
+
+If the property `true` becomes `true` *AFTER* `boot` was triggered, nothing will
+be executed. The condition `boot && property:true=true` will be evaluated to
+false because the `boot` trigger is a past event.
+
+Note that when `ro.property_service.async_persist_writes` is `true`, there is no
+defined ordering between persistent setprops and non-persistent setprops. For
+example:
+
+ on boot
+ setprop a 1
+ setprop persist.b 2
+
+When `ro.property_service.async_persist_writes` is `true`, triggers for these
+two properties may execute in any order.
Services
--------
@@ -184,8 +206,10 @@
capability without the "CAP\_" prefix, like "NET\_ADMIN" or "SETPCAP". See
http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
capabilities.
- If no capabilities are provided, then all capabilities are removed from this service, even if it
- runs as root.
+ If no capabilities are provided, then behaviour depends on the user the service runs under:
+ * if it's root, then the service will run with all the capabitilies (note: whether the
+ service can actually use them is controlled by selinux);
+ * otherwise all capabilities will be dropped.
`class <name> [ <name>\* ]`
> Specify class names for the service. All services in a
@@ -231,6 +255,10 @@
"r", "w" or "rw". For native executables see libcutils
android\_get\_control\_file().
+`gentle_kill`
+> This service will be sent SIGTERM instead of SIGKILL when stopped. After a 200 ms timeout, it will
+ be sent SIGKILL.
+
`group <groupname> [ <groupname>\* ]`
> Change to 'groupname' before exec'ing this service. Additional
groupnames beyond the (required) first one are used to set the
@@ -316,11 +344,14 @@
intended to be used with the `exec_start` builtin for any must-have checks during boot.
`restart_period <seconds>`
-> If a non-oneshot service exits, it will be restarted at its start time plus
- this period. It defaults to 5s to rate limit crashing services.
- This can be increased for services that are meant to run periodically. For
- example, it may be set to 3600 to indicate that the service should run every hour
- or 86400 to indicate that the service should run every day.
+> If a non-oneshot service exits, it will be restarted at its previous start time plus this period.
+ The default value is 5s. This can be used to implement periodic services together with the
+ `timeout_period` command below. For example, it may be set to 3600 to indicate that the service
+ should run every hour or 86400 to indicate that the service should run every day. This can be set
+ to a value shorter than 5s for example 0, but the minimum 5s delay is enforced if the restart was
+ due to a crash. This is to rate limit persistentally crashing services. In other words,
+ `<seconds>` smaller than 5 is respected only when the service exits deliverately and successfully
+ (i.e. by calling exit(0)).
`rlimit <resource> <cur> <max>`
> This applies the given rlimit to the service. rlimits are inherited by child
@@ -399,7 +430,7 @@
using this new mechanism, processes can use the user option to
select their desired uid without ever running as root.
As of Android O, processes can also request capabilities directly in their .rc
- files. See the "capabilities" option below.
+ files. See the "capabilities" option above.
`writepid <file> [ <file>\* ]`
> Write the child's pid to the given files when it forks. Meant for
@@ -433,7 +464,9 @@
For example:
`on boot && property:a=b` defines an action that is only executed when
-the 'boot' event trigger happens and the property a equals b.
+the 'boot' event trigger happens and the property a equals b at the moment. This
+will NOT be executed when the property a transitions to value b after the `boot`
+event was triggered.
`on property:a=b && property:c=d` defines an action that is executed
at three times:
@@ -612,17 +645,17 @@
the current SELinux policy or its parent if not specified in the policy. If
the directory exists, its security context will not be changed (even if
different from the policy).
-
- > _action_ can be one of:
- * `None`: take no encryption action; directory will be encrypted if parent is.
- * `Require`: encrypt directory, abort boot process if encryption fails
- * `Attempt`: try to set an encryption policy, but continue if it fails
- * `DeleteIfNecessary`: recursively delete directory if necessary to set
- encryption policy.
-
- > _key_ can be one of:
- * `ref`: use the systemwide DE key
- * `per_boot_ref`: use the key freshly generated on each boot.
+>
+> _action_ can be one of:
+> * `None`: take no encryption action; directory will be encrypted if parent is.
+> * `Require`: encrypt directory, abort boot process if encryption fails
+> * `Attempt`: try to set an encryption policy, but continue if it fails
+> * `DeleteIfNecessary`: recursively delete directory if necessary to set
+> encryption policy.
+>
+> _key_ can be one of:
+> * `ref`: use the systemwide DE key
+> * `per_boot_ref`: use the key freshly generated on each boot.
`mount_all [ <fstab> ] [--<option>]`
> Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional
diff --git a/init/action.cpp b/init/action.cpp
index 1e998ae..18f6360 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -30,7 +30,7 @@
Result<void> RunBuiltinFunction(const BuiltinFunction& function,
const std::vector<std::string>& args, const std::string& context) {
- auto builtin_arguments = BuiltinArguments(context);
+ BuiltinArguments builtin_arguments{.context = context};
builtin_arguments.args.resize(args.size());
builtin_arguments.args[0] = args[0];
@@ -69,7 +69,7 @@
}
Result<void> Command::CheckCommand() const {
- auto builtin_arguments = BuiltinArguments("host_init_verifier");
+ BuiltinArguments builtin_arguments{.context = "host_init_verifier"};
builtin_arguments.args.resize(args_.size());
builtin_arguments.args[0] = args_[0];
diff --git a/init/apex_init_util.cpp b/init/apex_init_util.cpp
index d618a6e..c818f8f 100644
--- a/init/apex_init_util.cpp
+++ b/init/apex_init_util.cpp
@@ -18,7 +18,6 @@
#include <glob.h>
-#include <map>
#include <vector>
#include <android-base/logging.h>
@@ -66,18 +65,20 @@
}
static Result<void> ParseConfigs(const std::vector<std::string>& configs) {
- Parser parser = CreateApexConfigParser(ActionManager::GetInstance(),
- ServiceList::GetInstance());
- bool success = true;
+ Parser parser =
+ CreateApexConfigParser(ActionManager::GetInstance(), ServiceList::GetInstance());
+ std::vector<std::string> errors;
for (const auto& c : configs) {
- success &= parser.ParseConfigFile(c);
+ auto result = parser.ParseConfigFile(c);
+ // We should handle other config files even when there's an error.
+ if (!result.ok()) {
+ errors.push_back(result.error().message());
+ }
}
-
- if (success) {
- return {};
- } else {
- return Error() << "Unable to parse apex configs";
+ if (!errors.empty()) {
+ return Error() << "Unable to parse apex configs: " << base::Join(errors, "|");
}
+ return {};
}
Result<void> ParseApexConfigs(const std::string& apex_name) {
diff --git a/init/builtin_arguments.h b/init/builtin_arguments.h
index 1742b78..890a216 100644
--- a/init/builtin_arguments.h
+++ b/init/builtin_arguments.h
@@ -24,10 +24,6 @@
namespace init {
struct BuiltinArguments {
- BuiltinArguments(const std::string& context) : context(context) {}
- BuiltinArguments(std::vector<std::string> args, const std::string& context)
- : args(std::move(args)), context(context) {}
-
const std::string& operator[](std::size_t i) const { return args[i]; }
auto begin() const { return args.begin(); }
auto end() const { return args.end(); }
diff --git a/init/builtins.cpp b/init/builtins.cpp
index a89813e..585eca2 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -60,6 +60,8 @@
#include <cutils/android_reboot.h>
#include <fs_mgr.h>
#include <fscrypt/fscrypt.h>
+#include <libdm/dm.h>
+#include <libdm/loop_control.h>
#include <libgsi/libgsi.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
@@ -506,29 +508,29 @@
if (android::base::StartsWith(source, "loop@")) {
int mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
- unique_fd fd(TEMP_FAILURE_RETRY(open(source + 5, mode | O_CLOEXEC)));
- if (fd < 0) return ErrnoError() << "open(" << source + 5 << ", " << mode << ") failed";
+ const char* file_path = source + strlen("loop@");
- for (size_t n = 0;; n++) {
- std::string tmp = android::base::StringPrintf("/dev/block/loop%zu", n);
- unique_fd loop(TEMP_FAILURE_RETRY(open(tmp.c_str(), mode | O_CLOEXEC)));
- if (loop < 0) return ErrnoError() << "open(" << tmp << ", " << mode << ") failed";
-
- loop_info info;
- /* if it is a blank loop device */
- if (ioctl(loop.get(), LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
- /* if it becomes our loop device */
- if (ioctl(loop.get(), LOOP_SET_FD, fd.get()) >= 0) {
- if (mount(tmp.c_str(), target, system, flags, options) < 0) {
- ioctl(loop.get(), LOOP_CLR_FD, 0);
- return ErrnoError() << "mount() failed";
- }
- return {};
- }
- }
+ // Open source file
+ if (wait) {
+ wait_for_file(file_path, kCommandRetryTimeout);
}
- return Error() << "out of loopback devices";
+ unique_fd fd(TEMP_FAILURE_RETRY(open(file_path, mode | O_CLOEXEC)));
+ if (fd < 0) {
+ return ErrnoError() << "open(" << file_path << ", " << mode << ") failed";
+ }
+
+ // Allocate loop device and attach it to file_path.
+ android::dm::LoopControl loop_control;
+ std::string loop_device;
+ if (!loop_control.Attach(fd.get(), 5s, &loop_device)) {
+ return ErrnoError() << "loop_control.Attach " << file_path << " failed";
+ }
+
+ if (mount(loop_device.c_str(), target, system, flags, options) < 0) {
+ loop_control.Detach(loop_device);
+ return ErrnoError() << "mount() failed";
+ }
} else {
if (wait)
wait_for_file(source, kCommandRetryTimeout);
@@ -1074,7 +1076,7 @@
static Result<void> do_restorecon_recursive(const BuiltinArguments& args) {
std::vector<std::string> non_const_args(args.args);
non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
- return do_restorecon({std::move(non_const_args), args.context});
+ return do_restorecon({.args = std::move(non_const_args), .context = args.context});
}
static Result<void> do_loglevel(const BuiltinArguments& args) {
diff --git a/init/check_builtins.cpp b/init/check_builtins.cpp
index 481fa31..461ed22 100644
--- a/init/check_builtins.cpp
+++ b/init/check_builtins.cpp
@@ -85,7 +85,7 @@
}
Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
- BuiltinArguments remaining_args(args.context);
+ BuiltinArguments remaining_args{.context = args.context};
remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
remaining_args.args[0] = args[0];
diff --git a/init/devices.cpp b/init/devices.cpp
index 28406f6..d29ffd6 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -32,6 +32,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <libdm/dm.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
#include <selinux/selinux.h>
@@ -112,17 +113,14 @@
// the supplied buffer with the dm module's instantiated name.
// If it doesn't start with a virtual block device, or there is some
// error, return false.
-static bool FindDmDevice(const std::string& path, std::string* name, std::string* uuid) {
- if (!StartsWith(path, "/devices/virtual/block/dm-")) return false;
+static bool FindDmDevice(const Uevent& uevent, std::string* name, std::string* uuid) {
+ if (!StartsWith(uevent.path, "/devices/virtual/block/dm-")) return false;
+ if (uevent.action == "remove") return false; // Avoid error spam from ioctl
- if (!ReadFileToString("/sys" + path + "/dm/name", name)) {
- return false;
- }
- ReadFileToString("/sys" + path + "/dm/uuid", uuid);
+ dev_t dev = makedev(uevent.major, uevent.minor);
- *name = android::base::Trim(*name);
- *uuid = android::base::Trim(*uuid);
- return true;
+ auto& dm = android::dm::DeviceMapper::Instance();
+ return dm.GetDeviceNameAndUuid(dev, name, uuid);
}
Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid,
@@ -392,7 +390,7 @@
type = "pci";
} else if (FindVbdDevicePrefix(uevent.path, &device)) {
type = "vbd";
- } else if (FindDmDevice(uevent.path, &partition, &uuid)) {
+ } else if (FindDmDevice(uevent, &partition, &uuid)) {
std::vector<std::string> symlinks = {"/dev/block/mapper/" + partition};
if (!uuid.empty()) {
symlinks.emplace_back("/dev/block/mapper/by-uuid/" + uuid);
@@ -431,6 +429,12 @@
}
}
+ std::string model;
+ if (ReadFileToString("/sys/class/block/" + uevent.device_name + "/queue/zoned", &model) &&
+ !StartsWith(model, "none")) {
+ links.emplace_back("/dev/block/by-name/zoned_device");
+ }
+
auto last_slash = uevent.path.rfind('/');
links.emplace_back(link_path + "/" + uevent.path.substr(last_slash + 1));
@@ -470,7 +474,11 @@
MakeDevice(devpath, block, major, minor, links);
}
- // We don't have full device-mapper information until a change event is fired.
+ // Handle device-mapper nodes.
+ // On kernels <= 5.10, the "add" event is fired on DM_DEV_CREATE, but does not contain name
+ // information until DM_TABLE_LOAD - thus, we wait for a "change" event.
+ // On kernels >= 5.15, the "add" event is fired on DM_TABLE_LOAD, followed by a "change"
+ // event.
if (action == "add" || (action == "change" && StartsWith(devpath, "/dev/block/dm-"))) {
for (const auto& link : links) {
if (!mkdir_recursive(Dirname(link), 0755)) {
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index b9fa58c..3c012fe 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -33,6 +33,7 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@@ -43,6 +44,7 @@
using android::base::Timer;
using android::base::Trim;
using android::base::unique_fd;
+using android::base::WaitForProperty;
using android::base::WriteFully;
namespace android {
@@ -82,6 +84,33 @@
return access("/dev/.booting", F_OK) == 0;
}
+static bool IsApexActivated() {
+ static bool apex_activated = []() {
+ // Wait for com.android.runtime.apex activation
+ // Property name and value must be kept in sync with system/apexd/apex/apex_constants.h
+ // 60s is the default firmware sysfs fallback timeout. (/sys/class/firmware/timeout)
+ if (!WaitForProperty("apexd.status", "activated", 60s)) {
+ LOG(ERROR) << "Apexd activation wait timeout";
+ return false;
+ }
+ return true;
+ }();
+
+ return apex_activated;
+}
+
+static bool NeedsRerunExternalHandler() {
+ static bool first = true;
+
+ // Rerun external handler only on the first try and when apex is activated
+ if (first) {
+ first = false;
+ return IsApexActivated();
+ }
+
+ return first;
+}
+
ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, gid_t gid,
std::string handler_path)
: devpath(std::move(devpath)), uid(uid), gid(gid), handler_path(std::move(handler_path)) {
@@ -210,6 +239,11 @@
auto result = RunExternalHandler(external_handler.handler_path, external_handler.uid,
external_handler.gid, uevent);
+ if (!result.ok() && NeedsRerunExternalHandler()) {
+ auto res = RunExternalHandler(external_handler.handler_path, external_handler.uid,
+ external_handler.gid, uevent);
+ result = std::move(res);
+ }
if (!result.ok()) {
LOG(ERROR) << "Using default firmware; External firmware handler failed: "
<< result.error();
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 107e99a..bff80c5 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -58,6 +58,12 @@
namespace {
+enum class BootMode {
+ NORMAL_MODE,
+ RECOVERY_MODE,
+ CHARGER_MODE,
+};
+
void FreeRamdisk(DIR* dir, dev_t dev) {
int dfd = dirfd(dir);
@@ -149,13 +155,27 @@
}
} // namespace
-std::string GetModuleLoadList(bool recovery, const std::string& dir_path) {
- auto module_load_file = "modules.load";
- if (recovery) {
- struct stat fileStat;
- std::string recovery_load_path = dir_path + "/modules.load.recovery";
- if (!stat(recovery_load_path.c_str(), &fileStat)) {
+std::string GetModuleLoadList(BootMode boot_mode, const std::string& dir_path) {
+ std::string module_load_file;
+
+ switch (boot_mode) {
+ case BootMode::NORMAL_MODE:
+ module_load_file = "modules.load";
+ break;
+ case BootMode::RECOVERY_MODE:
module_load_file = "modules.load.recovery";
+ break;
+ case BootMode::CHARGER_MODE:
+ module_load_file = "modules.load.charger";
+ break;
+ }
+
+ if (module_load_file != "modules.load") {
+ struct stat fileStat;
+ std::string load_path = dir_path + "/" + module_load_file;
+ // Fall back to modules.load if the other files aren't accessible
+ if (stat(load_path.c_str(), &fileStat)) {
+ module_load_file = "modules.load";
}
}
@@ -163,7 +183,8 @@
}
#define MODULE_BASE_DIR "/lib/modules"
-bool LoadKernelModules(bool recovery, bool want_console, bool want_parallel, int& modules_loaded) {
+bool LoadKernelModules(BootMode boot_mode, bool want_console, bool want_parallel,
+ int& modules_loaded) {
struct utsname uts;
if (uname(&uts)) {
LOG(FATAL) << "Failed to get kernel version.";
@@ -203,7 +224,7 @@
for (const auto& module_dir : module_dirs) {
std::string dir_path = MODULE_BASE_DIR "/";
dir_path.append(module_dir);
- Modprobe m({dir_path}, GetModuleLoadList(recovery, dir_path));
+ Modprobe m({dir_path}, GetModuleLoadList(boot_mode, dir_path));
bool retval = m.LoadListedModules(!want_console);
modules_loaded = m.GetModuleCount();
if (modules_loaded > 0) {
@@ -211,7 +232,7 @@
}
}
- Modprobe m({MODULE_BASE_DIR}, GetModuleLoadList(recovery, MODULE_BASE_DIR));
+ Modprobe m({MODULE_BASE_DIR}, GetModuleLoadList(boot_mode, MODULE_BASE_DIR));
bool retval = (want_parallel) ? m.LoadModulesParallel(std::thread::hardware_concurrency())
: m.LoadListedModules(!want_console);
modules_loaded = m.GetModuleCount();
@@ -221,6 +242,21 @@
return true;
}
+static bool IsChargerMode(const std::string& cmdline, const std::string& bootconfig) {
+ return bootconfig.find("androidboot.mode = \"charger\"") != std::string::npos ||
+ cmdline.find("androidboot.mode=charger") != std::string::npos;
+}
+
+static BootMode GetBootMode(const std::string& cmdline, const std::string& bootconfig)
+{
+ if (IsChargerMode(cmdline, bootconfig))
+ return BootMode::CHARGER_MODE;
+ else if (IsRecoveryMode() && !ForceNormalBoot(cmdline, bootconfig))
+ return BootMode::RECOVERY_MODE;
+
+ return BootMode::NORMAL_MODE;
+}
+
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@@ -328,7 +364,8 @@
boot_clock::time_point module_start_time = boot_clock::now();
int module_count = 0;
- if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline, bootconfig), want_console,
+ BootMode boot_mode = GetBootMode(cmdline, bootconfig);
+ if (!LoadKernelModules(boot_mode, want_console,
want_parallel, module_count)) {
if (want_console != FirstStageConsoleParam::DISABLED) {
LOG(ERROR) << "Failed to load kernel modules, starting console";
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/fuzzer/init_parser_fuzzer.cpp b/init/fuzzer/init_parser_fuzzer.cpp
index e6a78a2..dc76465 100644
--- a/init/fuzzer/init_parser_fuzzer.cpp
+++ b/init/fuzzer/init_parser_fuzzer.cpp
@@ -125,7 +125,7 @@
std::string path = fdp_.ConsumeBool() ? fdp_.PickValueInArray(kValidPaths)
: fdp_.ConsumeRandomLengthString(kMaxBytes);
parser.ParseConfig(path);
- parser.ParseConfigFileInsecure(path);
+ parser.ParseConfigFileInsecure(path, false /* follow_symlinks */);
}
void InitParserFuzzer::Process() {
diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp
index db127d3..f070776 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -326,7 +326,9 @@
}
}
} else {
- if (!parser.ParseConfigFileInsecure(*argv)) {
+ if (!parser.ParseConfigFileInsecure(*argv, true /* follow_symlinks */)) {
+ // Follow symlinks as inputs during build execution in Bazel's
+ // execution root are symlinks, unlike Soong or Make.
LOG(ERROR) << "Failed to open init rc script '" << *argv << "'";
return EXIT_FAILURE;
}
diff --git a/init/init.cpp b/init/init.cpp
index 4262191..da63fdc 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -51,6 +51,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr_vendor_overlay.h>
#include <keyutils.h>
@@ -211,16 +212,16 @@
}
private:
- void ResetWaitForPropLocked() {
+ void ResetWaitForPropLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
wait_prop_name_.clear();
wait_prop_value_.clear();
waiting_for_prop_.reset();
}
std::mutex lock_;
- std::unique_ptr<Timer> waiting_for_prop_{nullptr};
- std::string wait_prop_name_;
- std::string wait_prop_value_;
+ GUARDED_BY(lock_) std::unique_ptr<Timer> waiting_for_prop_{nullptr};
+ GUARDED_BY(lock_) std::string wait_prop_name_;
+ GUARDED_BY(lock_) std::string wait_prop_value_;
} prop_waiter_state;
@@ -246,48 +247,21 @@
WakeMainInitThread();
}
- std::optional<std::string> CheckShutdown() {
+ std::optional<std::string> CheckShutdown() __attribute__((warn_unused_result)) {
auto lock = std::lock_guard{shutdown_command_lock_};
if (do_shutdown_ && !IsShuttingDown()) {
+ do_shutdown_ = false;
return shutdown_command_;
}
return {};
}
- bool do_shutdown() const { return do_shutdown_; }
- void set_do_shutdown(bool value) { do_shutdown_ = value; }
-
private:
std::mutex shutdown_command_lock_;
- std::string shutdown_command_;
+ std::string shutdown_command_ GUARDED_BY(shutdown_command_lock_);
bool do_shutdown_ = false;
} shutdown_state;
-static void UnwindMainThreadStack() {
- unwindstack::AndroidLocalUnwinder unwinder;
- unwindstack::AndroidUnwinderData data;
- if (!unwinder.Unwind(data)) {
- LOG(ERROR) << __FUNCTION__
- << "sys.powerctl: Failed to unwind callstack: " << data.GetErrorString();
- }
- for (const auto& frame : data.frames) {
- LOG(ERROR) << "sys.powerctl: " << unwinder.FormatFrame(frame);
- }
-}
-
-void DebugRebootLogging() {
- LOG(INFO) << "sys.powerctl: do_shutdown: " << shutdown_state.do_shutdown()
- << " IsShuttingDown: " << IsShuttingDown();
- if (shutdown_state.do_shutdown()) {
- LOG(ERROR) << "sys.powerctl set while a previous shutdown command has not been handled";
- UnwindMainThreadStack();
- }
- if (IsShuttingDown()) {
- LOG(ERROR) << "sys.powerctl set while init is already shutting down";
- UnwindMainThreadStack();
- }
-}
-
void DumpState() {
ServiceList::GetInstance().DumpState();
ActionManager::GetInstance().DumpState();
@@ -952,6 +926,8 @@
InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
+ SelinuxSetupKernelLogging();
+
// Update $PATH in the case the second stage init is newer than first stage init, where it is
// first set.
if (setenv("PATH", _PATH_DEFPATH, 1) != 0) {
@@ -1012,7 +988,6 @@
MountExtraFilesystems();
// Now set up SELinux for second stage.
- SelinuxSetupKernelLogging();
SelabelInitialize();
SelinuxRestoreContext();
@@ -1068,6 +1043,12 @@
SetProperty(gsi::kGsiBootedProp, is_running);
auto is_installed = android::gsi::IsGsiInstalled() ? "1" : "0";
SetProperty(gsi::kGsiInstalledProp, is_installed);
+ if (android::gsi::IsGsiRunning()) {
+ std::string dsu_slot;
+ if (android::gsi::GetActiveDsu(&dsu_slot)) {
+ SetProperty(gsi::kDsuSlotProp, dsu_slot);
+ }
+ }
am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
@@ -1107,36 +1088,43 @@
// Restore prio before main loop
setpriority(PRIO_PROCESS, 0, 0);
while (true) {
- // By default, sleep until something happens.
- std::optional<std::chrono::milliseconds> epoll_timeout;
+ // By default, sleep until something happens. Do not convert far_future into
+ // std::chrono::milliseconds because that would trigger an overflow. The unit of boot_clock
+ // is 1ns.
+ const boot_clock::time_point far_future = boot_clock::time_point::max();
+ boot_clock::time_point next_action_time = far_future;
auto shutdown_command = shutdown_state.CheckShutdown();
if (shutdown_command) {
LOG(INFO) << "Got shutdown_command '" << *shutdown_command
<< "' Calling HandlePowerctlMessage()";
HandlePowerctlMessage(*shutdown_command);
- shutdown_state.set_do_shutdown(false);
}
if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
am.ExecuteOneCommand();
+ // If there's more work to do, wake up again immediately.
+ if (am.HasMoreCommands()) {
+ next_action_time = boot_clock::now();
+ }
}
+ // Since the above code examined pending actions, no new actions must be
+ // queued by the code between this line and the Epoll::Wait() call below
+ // without calling WakeMainInitThread().
if (!IsShuttingDown()) {
auto next_process_action_time = HandleProcessActions();
// If there's a process that needs restarting, wake up in time for that.
if (next_process_action_time) {
- epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
- *next_process_action_time - boot_clock::now());
- if (epoll_timeout < 0ms) epoll_timeout = 0ms;
+ next_action_time = std::min(next_action_time, *next_process_action_time);
}
}
- if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
- // If there's more work to do, wake up again immediately.
- if (am.HasMoreCommands()) epoll_timeout = 0ms;
+ std::optional<std::chrono::milliseconds> epoll_timeout;
+ if (next_action_time != far_future) {
+ epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
+ std::max(next_action_time - boot_clock::now(), 0ns));
}
-
auto epoll_result = epoll.Wait(epoll_timeout);
if (!epoll_result.ok()) {
LOG(ERROR) << epoll_result.error();
diff --git a/init/init.h b/init/init.h
index 063632a..9c7e918 100644
--- a/init/init.h
+++ b/init/init.h
@@ -42,8 +42,6 @@
void PropertyChanged(const std::string& name, const std::string& value);
bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd);
-void DebugRebootLogging();
-
int SecondStageMain(int argc, char** argv);
int StopServicesFromApex(const std::string& apex_name);
diff --git a/init/init_test.cpp b/init/init_test.cpp
index aea1cb3..7e8513b 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -14,15 +14,20 @@
* limitations under the License.
*/
+#include <fstream>
#include <functional>
#include <string_view>
+#include <thread>
#include <type_traits>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android/api-level.h>
#include <gtest/gtest.h>
#include <selinux/selinux.h>
+#include <sys/resource.h>
#include "action.h"
#include "action_manager.h"
@@ -41,6 +46,7 @@
using android::base::GetIntProperty;
using android::base::GetProperty;
using android::base::SetProperty;
+using android::base::StringPrintf;
using android::base::StringReplace;
using android::base::WaitForProperty;
using namespace std::literals;
@@ -174,9 +180,11 @@
std::string init_script = R"init(
service A something
class first
+ user nobody
service A something
class second
+ user nobody
override
)init";
@@ -194,13 +202,18 @@
}
TEST(init, StartConsole) {
- if (access("/dev/console", F_OK) < 0) {
- GTEST_SKIP() << "/dev/console not found";
+ if (GetProperty("ro.build.type", "") == "user") {
+ GTEST_SKIP() << "Must run on userdebug/eng builds. b/262090304";
+ return;
+ }
+ if (getuid() != 0) {
+ GTEST_SKIP() << "Must be run as root.";
+ return;
}
std::string init_script = R"init(
service console /system/bin/sh
class core
- console console
+ console null
disabled
user root
group root shell log readproc
@@ -599,6 +612,31 @@
EXPECT_EQ(2, num_executed);
}
+TEST(init, RejectsNoUserStartingInV) {
+ std::string init_script =
+ R"init(
+service A something
+ class first
+)init";
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
+
+ ServiceList service_list;
+ Parser parser;
+ parser.AddSectionParser("service",
+ std::make_unique<ServiceParser>(&service_list, nullptr, std::nullopt));
+
+ ASSERT_TRUE(parser.ParseConfig(tf.path));
+
+ if (GetIntProperty("ro.vendor.api_level", 0) > __ANDROID_API_U__) {
+ ASSERT_EQ(1u, parser.parse_error_count());
+ } else {
+ ASSERT_EQ(0u, parser.parse_error_count());
+ }
+}
+
TEST(init, RejectsCriticalAndOneshotService) {
if (GetIntProperty("ro.product.first_api_level", 10000) < 30) {
GTEST_SKIP() << "Test only valid for devices launching with R or later";
@@ -608,6 +646,7 @@
R"init(
service A something
class first
+ user root
critical
oneshot
)init";
@@ -625,6 +664,115 @@
ASSERT_EQ(1u, parser.parse_error_count());
}
+TEST(init, MemLockLimit) {
+ // Test is enforced only for U+ devices
+ if (android::base::GetIntProperty("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
+ GTEST_SKIP();
+ }
+
+ // Verify we are running memlock at, or under, 64KB
+ const unsigned long max_limit = 65536;
+ struct rlimit curr_limit;
+ ASSERT_EQ(getrlimit(RLIMIT_MEMLOCK, &curr_limit), 0);
+ ASSERT_LE(curr_limit.rlim_cur, max_limit);
+ ASSERT_LE(curr_limit.rlim_max, max_limit);
+}
+
+void CloseAllFds() {
+ DIR* dir;
+ struct dirent* ent;
+ int fd;
+
+ if ((dir = opendir("/proc/self/fd"))) {
+ while ((ent = readdir(dir))) {
+ if (sscanf(ent->d_name, "%d", &fd) == 1) {
+ close(fd);
+ }
+ }
+ closedir(dir);
+ }
+}
+
+pid_t ForkExecvpAsync(const char* argv[]) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ // Child process.
+ CloseAllFds();
+
+ execvp(argv[0], const_cast<char**>(argv));
+ PLOG(ERROR) << "exec in ForkExecvpAsync init test";
+ _exit(EXIT_FAILURE);
+ }
+ // Parent process.
+ if (pid == -1) {
+ PLOG(ERROR) << "fork in ForkExecvpAsync init test";
+ return -1;
+ }
+ return pid;
+}
+
+pid_t TracerPid(pid_t pid) {
+ static constexpr std::string_view prefix{"TracerPid:"};
+ std::ifstream is(StringPrintf("/proc/%d/status", pid));
+ std::string line;
+ while (std::getline(is, line)) {
+ if (line.find(prefix) == 0) {
+ return atoi(line.substr(prefix.length()).c_str());
+ }
+ }
+ return -1;
+}
+
+TEST(init, GentleKill) {
+ if (getuid() != 0) {
+ GTEST_SKIP() << "Must be run as root.";
+ return;
+ }
+ std::string init_script = R"init(
+service test_gentle_kill /system/bin/sleep 1000
+ disabled
+ oneshot
+ gentle_kill
+ user root
+ group root
+ seclabel u:r:toolbox:s0
+)init";
+
+ ActionManager action_manager;
+ ServiceList service_list;
+ TestInitText(init_script, BuiltinFunctionMap(), {}, &action_manager, &service_list);
+ ASSERT_EQ(std::distance(service_list.begin(), service_list.end()), 1);
+
+ auto service = service_list.begin()->get();
+ ASSERT_NE(service, nullptr);
+ ASSERT_RESULT_OK(service->Start());
+ const pid_t pid = service->pid();
+ ASSERT_GT(pid, 0);
+ EXPECT_NE(getsid(pid), 0);
+
+ TemporaryFile logfile;
+ logfile.DoNotRemove();
+ ASSERT_TRUE(logfile.fd != -1);
+
+ std::string pid_str = std::to_string(pid);
+ const char* argv[] = {"/system/bin/strace", "-o", logfile.path, "-e", "signal", "-p",
+ pid_str.c_str(), nullptr};
+ pid_t strace_pid = ForkExecvpAsync(argv);
+
+ // Give strace the chance to connect
+ while (TracerPid(pid) == 0) {
+ std::this_thread::sleep_for(10ms);
+ }
+ service->Stop();
+
+ int status;
+ waitpid(strace_pid, &status, 0);
+
+ std::string logs;
+ android::base::ReadFdToString(logfile.fd, &logs);
+ ASSERT_NE(logs.find("killed by SIGTERM"), std::string::npos);
+}
+
class TestCaseLogger : public ::testing::EmptyTestEventListener {
void OnTestStart(const ::testing::TestInfo& test_info) override {
#ifdef __ANDROID__
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/parser.cpp b/init/parser.cpp
index 0a388db..8c0bb2b 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -131,9 +131,9 @@
}
}
-bool Parser::ParseConfigFileInsecure(const std::string& path) {
+bool Parser::ParseConfigFileInsecure(const std::string& path, bool follow_symlinks = false) {
std::string config_contents;
- if (!android::base::ReadFileToString(path, &config_contents)) {
+ if (!android::base::ReadFileToString(path, &config_contents, follow_symlinks)) {
return false;
}
@@ -141,19 +141,19 @@
return true;
}
-bool Parser::ParseConfigFile(const std::string& path) {
+Result<void> Parser::ParseConfigFile(const std::string& path) {
LOG(INFO) << "Parsing file " << path << "...";
android::base::Timer t;
auto config_contents = ReadFile(path);
if (!config_contents.ok()) {
- LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
- return false;
+ return Error() << "Unable to read config file '" << path
+ << "': " << config_contents.error();
}
ParseData(path, &config_contents.value());
LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
- return true;
+ return {};
}
bool Parser::ParseConfigDir(const std::string& path) {
@@ -176,8 +176,8 @@
// Sort first so we load files in a consistent order (bug 31996208)
std::sort(files.begin(), files.end());
for (const auto& file : files) {
- if (!ParseConfigFile(file)) {
- LOG(ERROR) << "could not import file '" << file << "'";
+ if (auto result = ParseConfigFile(file); !result.ok()) {
+ LOG(ERROR) << "could not import file '" << file << "': " << result.error();
}
}
return true;
@@ -187,7 +187,11 @@
if (is_dir(path.c_str())) {
return ParseConfigDir(path);
}
- return ParseConfigFile(path);
+ auto result = ParseConfigFile(path);
+ if (!result.ok()) {
+ LOG(INFO) << result.error();
+ }
+ return result.ok();
}
} // namespace init
diff --git a/init/parser.h b/init/parser.h
index 95b0cd7..8e5bca7 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,12 +72,12 @@
Parser();
bool ParseConfig(const std::string& path);
- bool ParseConfigFile(const std::string& path);
+ Result<void> ParseConfigFile(const std::string& path);
void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
void AddSingleLineParser(const std::string& prefix, LineCallback callback);
// Host init verifier check file permissions.
- bool ParseConfigFileInsecure(const std::string& path);
+ bool ParseConfigFileInsecure(const std::string& path, bool follow_symlinks);
size_t parse_error_count() const { return parse_error_count_; }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 9df9828..8da6982 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -98,6 +98,9 @@
namespace android {
namespace init {
+
+class PersistWriteThread;
+
constexpr auto FINGERPRINT_PROP = "ro.build.fingerprint";
constexpr auto LEGACY_FINGERPRINT_PROP = "ro.build.legacy.fingerprint";
constexpr auto ID_PROP = "ro.build.id";
@@ -115,6 +118,8 @@
static std::mutex accept_messages_lock;
static std::thread property_service_thread;
+static std::unique_ptr<PersistWriteThread> persist_write_thread;
+
static PropertyInfoAreaFile property_info_area;
struct PropertyAuditData {
@@ -177,48 +182,13 @@
return has_access;
}
-static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
- size_t valuelen = value.size();
-
- if (!IsLegalPropertyName(name)) {
- *error = "Illegal property name";
- return PROP_ERROR_INVALID_NAME;
- }
-
- if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
- *error = result.error().message();
- return PROP_ERROR_INVALID_VALUE;
- }
-
- prop_info* pi = (prop_info*) __system_property_find(name.c_str());
- if (pi != nullptr) {
- // ro.* properties are actually "write-once".
- if (StartsWith(name, "ro.")) {
- *error = "Read-only property was already set";
- return PROP_ERROR_READ_ONLY_PROPERTY;
- }
-
- __system_property_update(pi, value.c_str(), valuelen);
- } else {
- int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
- if (rc < 0) {
- *error = "__system_property_add failed";
- return PROP_ERROR_SET_FAILED;
- }
- }
-
- // Don't write properties to disk until after we have read all default
- // properties to prevent them from being overwritten by default values.
- if (persistent_properties_loaded && StartsWith(name, "persist.")) {
- WritePersistentProperty(name, value);
- }
+void NotifyPropertyChange(const std::string& name, const std::string& value) {
// If init hasn't started its main loop, then it won't be handling property changed messages
// anyway, so there's no need to try to send them.
auto lock = std::lock_guard{accept_messages_lock};
if (accept_messages) {
PropertyChanged(name, value);
}
- return PROP_SUCCESS;
}
class AsyncRestorecon {
@@ -259,7 +229,9 @@
class SocketConnection {
public:
+ SocketConnection() = default;
SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {}
+ SocketConnection(SocketConnection&&) = default;
bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) {
return RecvFully(value, sizeof(*value), timeout_ms);
@@ -318,6 +290,8 @@
const ucred& cred() { return cred_; }
+ SocketConnection& operator=(SocketConnection&&) = default;
+
private:
bool PollIn(uint32_t* timeout_ms) {
struct pollfd ufd = {
@@ -388,9 +362,78 @@
unique_fd socket_;
ucred cred_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection);
+ DISALLOW_COPY_AND_ASSIGN(SocketConnection);
};
+class PersistWriteThread {
+ public:
+ PersistWriteThread();
+ void Write(std::string name, std::string value, SocketConnection socket);
+
+ private:
+ void Work();
+
+ private:
+ std::thread thread_;
+ std::mutex mutex_;
+ std::condition_variable cv_;
+ std::deque<std::tuple<std::string, std::string, SocketConnection>> work_;
+};
+
+static std::optional<uint32_t> PropertySet(const std::string& name, const std::string& value,
+ SocketConnection* socket, std::string* error) {
+ size_t valuelen = value.size();
+
+ if (!IsLegalPropertyName(name)) {
+ *error = "Illegal property name";
+ return {PROP_ERROR_INVALID_NAME};
+ }
+
+ if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
+ *error = result.error().message();
+ return {PROP_ERROR_INVALID_VALUE};
+ }
+
+ prop_info* pi = (prop_info*)__system_property_find(name.c_str());
+ if (pi != nullptr) {
+ // ro.* properties are actually "write-once".
+ if (StartsWith(name, "ro.")) {
+ *error = "Read-only property was already set";
+ return {PROP_ERROR_READ_ONLY_PROPERTY};
+ }
+
+ __system_property_update(pi, value.c_str(), valuelen);
+ } else {
+ int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
+ if (rc < 0) {
+ *error = "__system_property_add failed";
+ return {PROP_ERROR_SET_FAILED};
+ }
+ }
+
+ // Don't write properties to disk until after we have read all default
+ // properties to prevent them from being overwritten by default values.
+ if (socket && persistent_properties_loaded && StartsWith(name, "persist.")) {
+ if (persist_write_thread) {
+ persist_write_thread->Write(name, value, std::move(*socket));
+ return {};
+ }
+ WritePersistentProperty(name, value);
+ }
+
+ NotifyPropertyChange(name, value);
+ return {PROP_SUCCESS};
+}
+
+// Helper for PropertySet, for the case where no socket is used, and therefore an asynchronous
+// return is not possible.
+static uint32_t PropertySetNoSocket(const std::string& name, const std::string& value,
+ std::string* error) {
+ auto ret = PropertySet(name, value, nullptr, error);
+ CHECK(ret.has_value());
+ return *ret;
+}
+
static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
SocketConnection* socket, std::string* error) {
auto lock = std::lock_guard{accept_messages_lock};
@@ -481,16 +524,17 @@
return PROP_SUCCESS;
}
-// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
-uint32_t HandlePropertySet(const std::string& name, const std::string& value,
- const std::string& source_context, const ucred& cr,
- SocketConnection* socket, std::string* error) {
+// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*, or std::nullopt
+// if asynchronous.
+std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::string& value,
+ const std::string& source_context, const ucred& cr,
+ SocketConnection* socket, std::string* error) {
if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) {
- return ret;
+ return {ret};
}
if (StartsWith(name, "ctl.")) {
- return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error);
+ return {SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error)};
}
// sys.powerctl is a special property that is used to make the device reboot. We want to log
@@ -506,12 +550,9 @@
}
LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
<< process_log_string;
- if (!value.empty()) {
- DebugRebootLogging();
- }
if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) {
*error = "Userspace reboot is not supported by this device";
- return PROP_ERROR_INVALID_VALUE;
+ return {PROP_ERROR_INVALID_VALUE};
}
}
@@ -522,10 +563,20 @@
if (name == kRestoreconProperty && cr.pid != 1 && !value.empty()) {
static AsyncRestorecon async_restorecon;
async_restorecon.TriggerRestorecon(value);
- return PROP_SUCCESS;
+ return {PROP_SUCCESS};
}
- return PropertySet(name, value, error);
+ return PropertySet(name, value, socket, error);
+}
+
+// Helper for HandlePropertySet, for the case where no socket is used, and
+// therefore an asynchronous return is not possible.
+uint32_t HandlePropertySetNoSocket(const std::string& name, const std::string& value,
+ const std::string& source_context, const ucred& cr,
+ std::string* error) {
+ auto ret = HandlePropertySet(name, value, source_context, cr, nullptr, error);
+ CHECK(ret.has_value());
+ return *ret;
}
static void handle_property_set_fd() {
@@ -576,8 +627,7 @@
const auto& cr = socket.cred();
std::string error;
- uint32_t result =
- HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error);
+ auto result = HandlePropertySetNoSocket(prop_name, prop_value, source_context, cr, &error);
if (result != PROP_SUCCESS) {
LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid
<< " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
@@ -603,14 +653,19 @@
return;
}
+ // HandlePropertySet takes ownership of the socket if the set is handled asynchronously.
const auto& cr = socket.cred();
std::string error;
- uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error);
- if (result != PROP_SUCCESS) {
+ auto result = HandlePropertySet(name, value, source_context, cr, &socket, &error);
+ if (!result) {
+ // Result will be sent after completion.
+ return;
+ }
+ if (*result != PROP_SUCCESS) {
LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid
<< " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
}
- socket.SendUint32(result);
+ socket.SendUint32(*result);
break;
}
@@ -622,10 +677,9 @@
}
uint32_t InitPropertySet(const std::string& name, const std::string& value) {
- uint32_t result = 0;
ucred cr = {.pid = 1, .uid = 0, .gid = 0};
std::string error;
- result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
+ auto result = HandlePropertySetNoSocket(name, value, kInitContext, cr, &error);
if (result != PROP_SUCCESS) {
LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
}
@@ -795,7 +849,7 @@
load_properties_from_file("/data/local.prop", nullptr, &properties);
for (const auto& [name, value] : properties) {
std::string error;
- if (PropertySet(name, value, &error) != PROP_SUCCESS) {
+ if (PropertySetNoSocket(name, value, &error) != PROP_SUCCESS) {
LOG(ERROR) << "Could not set '" << name << "' to '" << value
<< "' in /data/local.prop: " << error;
}
@@ -861,7 +915,7 @@
LOG(INFO) << "Setting product property " << base_prop << " to '" << target_prop_val
<< "' (from " << target_prop << ")";
std::string error;
- uint32_t res = PropertySet(base_prop, target_prop_val, &error);
+ auto res = PropertySetNoSocket(base_prop, target_prop_val, &error);
if (res != PROP_SUCCESS) {
LOG(ERROR) << "Error setting product property " << base_prop << ": err=" << res
<< " (" << error << ")";
@@ -890,7 +944,7 @@
}
std::string error;
- auto res = PropertySet(ID_PROP, build_id, &error);
+ auto res = PropertySetNoSocket(ID_PROP, build_id, &error);
if (res != PROP_SUCCESS) {
LOG(ERROR) << "Failed to set " << ID_PROP << " to " << build_id;
}
@@ -938,7 +992,7 @@
<< legacy_build_fingerprint << "'";
std::string error;
- uint32_t res = PropertySet(LEGACY_FINGERPRINT_PROP, legacy_build_fingerprint, &error);
+ auto res = PropertySetNoSocket(LEGACY_FINGERPRINT_PROP, legacy_build_fingerprint, &error);
if (res != PROP_SUCCESS) {
LOG(ERROR) << "Error setting property '" << LEGACY_FINGERPRINT_PROP << "': err=" << res
<< " (" << error << ")";
@@ -956,7 +1010,7 @@
LOG(INFO) << "Setting property '" << FINGERPRINT_PROP << "' to '" << build_fingerprint << "'";
std::string error;
- uint32_t res = PropertySet(FINGERPRINT_PROP, build_fingerprint, &error);
+ auto res = PropertySetNoSocket(FINGERPRINT_PROP, build_fingerprint, &error);
if (res != PROP_SUCCESS) {
LOG(ERROR) << "Error setting property '" << FINGERPRINT_PROP << "': err=" << res << " ("
<< error << ")";
@@ -1018,7 +1072,7 @@
LOG(INFO) << "Setting property '" << prop << "' to '" << prop_val << "'";
std::string error;
- uint32_t res = PropertySet(prop, prop_val, &error);
+ auto res = PropertySetNoSocket(prop, prop_val, &error);
if (res != PROP_SUCCESS) {
LOG(ERROR) << "Error setting property '" << prop << "': err=" << res << " (" << error
<< ")";
@@ -1052,7 +1106,7 @@
int api_level = std::min(read_api_level_props(BOARD_API_LEVEL_PROPS),
read_api_level_props(DEVICE_API_LEVEL_PROPS));
std::string error;
- uint32_t res = PropertySet(VENDOR_API_LEVEL_PROP, std::to_string(api_level), &error);
+ auto res = PropertySetNoSocket(VENDOR_API_LEVEL_PROP, std::to_string(api_level), &error);
if (res != PROP_SUCCESS) {
LOG(ERROR) << "Failed to set " << VENDOR_API_LEVEL_PROP << " with " << api_level << ": "
<< error << "(" << res << ")";
@@ -1146,7 +1200,7 @@
for (const auto& [name, value] : properties) {
std::string error;
- if (PropertySet(name, value, &error) != PROP_SUCCESS) {
+ if (PropertySetNoSocket(name, value, &error) != PROP_SUCCESS) {
LOG(ERROR) << "Could not set '" << name << "' to '" << value
<< "' while loading .prop files" << error;
}
@@ -1388,6 +1442,46 @@
}
}
+PersistWriteThread::PersistWriteThread() {
+ auto new_thread = std::thread([this]() -> void { Work(); });
+ thread_.swap(new_thread);
+}
+
+void PersistWriteThread::Work() {
+ while (true) {
+ std::tuple<std::string, std::string, SocketConnection> item;
+
+ // Grab the next item within the lock.
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ while (work_.empty()) {
+ cv_.wait(lock);
+ }
+
+ item = std::move(work_.front());
+ work_.pop_front();
+ }
+
+ std::this_thread::sleep_for(1s);
+
+ // Perform write/fsync outside the lock.
+ WritePersistentProperty(std::get<0>(item), std::get<1>(item));
+ NotifyPropertyChange(std::get<0>(item), std::get<1>(item));
+
+ SocketConnection& socket = std::get<2>(item);
+ socket.SendUint32(PROP_SUCCESS);
+ }
+}
+
+void PersistWriteThread::Write(std::string name, std::string value, SocketConnection socket) {
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ work_.emplace_back(std::move(name), std::move(value), std::move(socket));
+ }
+ cv_.notify_all();
+}
+
void StartPropertyService(int* epoll_socket) {
InitPropertySet("ro.property_service.version", "2");
@@ -1412,6 +1506,13 @@
auto new_thread = std::thread{PropertyServiceThread};
property_service_thread.swap(new_thread);
+
+ auto async_persist_writes =
+ android::base::GetBoolProperty("ro.property_service.async_persist_writes", false);
+
+ if (async_persist_writes) {
+ persist_write_thread = std::make_unique<PersistWriteThread>();
+ }
}
} // namespace init
diff --git a/init/property_service.h b/init/property_service.h
index 2d49a36..71a609c 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -18,7 +18,11 @@
#include <sys/socket.h>
+#include <condition_variable>
+#include <deque>
+#include <mutex>
#include <string>
+#include <thread>
#include "epoll.h"
diff --git a/init/reboot.cpp b/init/reboot.cpp
index a3fc534..3351c4c 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -51,6 +51,7 @@
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <fs_mgr.h>
+#include <libsnapshot/snapshot.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
#include <selinux/selinux.h>
@@ -422,11 +423,31 @@
if (run_fsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) {
return UMOUNT_STAT_ERROR;
}
-
+ auto sm = snapshot::SnapshotManager::New();
+ bool ota_update_in_progress = false;
+ if (sm->IsUserspaceSnapshotUpdateInProgress()) {
+ LOG(INFO) << "OTA update in progress";
+ ota_update_in_progress = true;
+ }
UmountStat stat = UmountPartitions(timeout - t.duration());
if (stat != UMOUNT_STAT_SUCCESS) {
LOG(INFO) << "umount timeout, last resort, kill all and try";
if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
+ // Since umount timedout, we will try to kill all processes
+ // and do one more attempt to umount the partitions.
+ //
+ // However, if OTA update is in progress, we don't want
+ // to kill the snapuserd daemon as the daemon will
+ // be serving I/O requests. Killing the daemon will
+ // end up with I/O failures. If the update is in progress,
+ // we will just return the umount failure status immediately.
+ // This is ok, given the fact that killing the processes
+ // and doing an umount is just a last effort. We are
+ // still not doing fsck when all processes are killed.
+ //
+ if (ota_update_in_progress) {
+ return stat;
+ }
KillAllProcesses();
// even if it succeeds, still it is timeout and do not run fsck with all processes killed
UmountStat st = UmountPartitions(0ms);
@@ -659,8 +680,8 @@
<< "': " << result.error();
}
s->SetShutdownCritical();
- } else if (do_shutdown_animation) {
- continue;
+ } else if (do_shutdown_animation && s->classnames().count("animation") > 0) {
+ // Need these for shutdown animations.
} else if (s->IsShutdownCritical()) {
// Start shutdown critical service if not started.
if (auto result = s->Start(); !result.ok()) {
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ea308aa..e0ef491 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -498,7 +498,7 @@
bool OpenMonolithicPolicy(PolicyFile* policy_file) {
static constexpr char kSepolicyFile[] = "/sepolicy";
- LOG(VERBOSE) << "Opening SELinux policy from monolithic file";
+ 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";
@@ -629,7 +629,7 @@
}
Result<void> SepolicyFsVerityCheck() {
- return Error() << "TODO implementent support for fsverity SEPolicy.";
+ return Error() << "TODO implement support for fsverity SEPolicy.";
}
Result<void> SepolicyCheckSignature(const std::string& dir) {
@@ -761,15 +761,7 @@
constexpr size_t kKlogMessageSize = 1024;
-void SelinuxAvcLog(char* buf, size_t buf_len) {
- CHECK_GT(buf_len, 0u);
-
- size_t str_len = strnlen(buf, buf_len);
- // trim newline at end of string
- if (buf[str_len - 1] == '\n') {
- buf[str_len - 1] = '\0';
- }
-
+void SelinuxAvcLog(char* buf) {
struct NetlinkMessage {
nlmsghdr hdr;
char buf[kKlogMessageSize];
@@ -835,8 +827,17 @@
if (length_written <= 0) {
return 0;
}
+
+ // libselinux log messages usually contain a new line character, while
+ // Android LOG() does not expect it. Remove it to avoid empty lines in
+ // the log buffers.
+ size_t str_len = strlen(buf);
+ if (buf[str_len - 1] == '\n') {
+ buf[str_len - 1] = '\0';
+ }
+
if (type == SELINUX_AVC) {
- SelinuxAvcLog(buf, sizeof(buf));
+ SelinuxAvcLog(buf);
} else {
android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
}
@@ -850,6 +851,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,
@@ -897,29 +902,31 @@
continue;
}
- auto system_entry = GetEntryForMountPoint(&fstab, "/system");
- if (!system_entry) {
- LOG(ERROR) << "Could not find mount entry for /system";
- break;
- }
- if (!system_entry->fs_mgr_flags.logical) {
- LOG(INFO) << "Skipping mount of " << name << ", system is not dynamic.";
- break;
- }
+ auto system_entries = GetEntriesForMountPoint(&fstab, "/system");
+ for (auto& system_entry : system_entries) {
+ if (!system_entry) {
+ LOG(ERROR) << "Could not find mount entry for /system";
+ break;
+ }
+ if (!system_entry->fs_mgr_flags.logical) {
+ LOG(INFO) << "Skipping mount of " << name << ", system is not dynamic.";
+ break;
+ }
- auto entry = *system_entry;
- auto partition_name = name + fs_mgr_get_slot_suffix();
- auto replace_name = "system"s + fs_mgr_get_slot_suffix();
+ auto entry = *system_entry;
+ auto partition_name = name + fs_mgr_get_slot_suffix();
+ auto replace_name = "system"s + fs_mgr_get_slot_suffix();
- entry.mount_point = "/"s + name;
- entry.blk_device =
+ entry.mount_point = "/"s + name;
+ entry.blk_device =
android::base::StringReplace(entry.blk_device, replace_name, partition_name, false);
- if (!fs_mgr_update_logical_partition(&entry)) {
- LOG(ERROR) << "Could not update logical partition";
- continue;
- }
+ if (!fs_mgr_update_logical_partition(&entry)) {
+ LOG(ERROR) << "Could not update logical partition";
+ continue;
+ }
- extra_fstab.emplace_back(std::move(entry));
+ extra_fstab.emplace_back(std::move(entry));
+ }
}
SkipMountingPartitions(&extra_fstab, true /* verbose */);
@@ -951,6 +958,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
@@ -966,20 +993,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();
@@ -991,9 +1007,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();
}
@@ -1011,6 +1026,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 2ce81a0..a0b3478 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -26,6 +26,7 @@
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
+#include <thread>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -49,7 +50,6 @@
#endif
#ifdef INIT_FULL_SOURCES
-#include <ApexProperties.sysprop.h>
#include <android/api-level.h>
#include "mount_namespace.h"
@@ -139,9 +139,10 @@
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
const std::string& filename, const std::vector<std::string>& args)
- : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, filename, args) {}
+ : Service(name, 0, std::nullopt, 0, {}, 0, "", subcontext_for_restart_commands, filename,
+ args) {}
-Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
+Service::Service(const std::string& name, unsigned flags, std::optional<uid_t> uid, gid_t gid,
const std::vector<gid_t>& supp_gids, int namespace_flags,
const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
const std::string& filename, const std::vector<std::string>& args)
@@ -152,7 +153,7 @@
crash_count_(0),
proc_attr_{.ioprio_class = IoSchedClass_NONE,
.ioprio_pri = 0,
- .uid = uid,
+ .parsed_uid = uid,
.gid = gid,
.supp_gids = supp_gids,
.priority = 0},
@@ -204,9 +205,9 @@
int max_processes = 0;
int r;
if (signal == SIGTERM) {
- r = killProcessGroupOnce(proc_attr_.uid, pid_, signal, &max_processes);
+ r = killProcessGroupOnce(uid(), pid_, signal, &max_processes);
} else {
- r = killProcessGroup(proc_attr_.uid, pid_, signal, &max_processes);
+ r = killProcessGroup(uid(), pid_, signal, &max_processes);
}
if (report_oneshot && max_processes > 0) {
@@ -227,7 +228,7 @@
void Service::SetProcessAttributesAndCaps(InterprocessFifo setsid_finished) {
// Keep capabilites on uid change.
- if (capabilities_ && proc_attr_.uid) {
+ if (capabilities_ && uid()) {
// If Android is running in a container, some securebits might already
// be locked, so don't change those.
unsigned long securebits = prctl(PR_GET_SECUREBITS);
@@ -254,7 +255,7 @@
if (!SetCapsForExec(*capabilities_)) {
LOG(FATAL) << "cannot set capabilities for " << name_;
}
- } else if (proc_attr_.uid) {
+ } else if (uid()) {
// Inheritable caps can be non-zero when running in a container.
if (!DropInheritableCaps()) {
LOG(FATAL) << "cannot drop inheritable caps for " << name_;
@@ -306,6 +307,7 @@
pid_ = 0;
flags_ &= (~SVC_RUNNING);
start_order_ = 0;
+ was_last_exit_ok_ = siginfo.si_code == CLD_EXITED && siginfo.si_status == 0;
// Oneshot processes go into the disabled state on exit,
// except when manually restarted.
@@ -320,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
@@ -359,7 +361,8 @@
// If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed,
// reboot into bootloader or set crashing property
boot_clock::time_point now = boot_clock::now();
- if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART)) {
+ if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART) &&
+ !was_last_exit_ok_) {
bool boot_completed = GetBoolProperty("sys.boot_completed", false);
if (now < time_crashed_ + fatal_crash_window_ || !boot_completed) {
if (++crash_count_ > 4) {
@@ -433,8 +436,8 @@
flags_ |= SVC_EXEC;
is_exec_service_running_ = true;
- LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << proc_attr_.uid
- << " gid " << proc_attr_.gid << "+" << proc_attr_.supp_gids.size() << " context "
+ LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << uid() << " gid "
+ << proc_attr_.gid << "+" << proc_attr_.supp_gids.size() << " context "
<< (!seclabel_.empty() ? seclabel_ : "default") << ") started; waiting...";
reboot_on_failure.Disable();
@@ -446,6 +449,16 @@
return {};
}
+ // On newer kernels, /dev/console will always exist because
+ // "console=ttynull" is hard-coded in CONFIG_CMDLINE. This new boot
+ // property should be set via "androidboot.serialconsole=0" to explicitly
+ // disable services requiring the console. For older kernels and boot
+ // images, not setting this at all will fall back to the old behavior
+ if (GetProperty("ro.boot.serialconsole", "") == "0") {
+ flags_ |= SVC_DISABLED;
+ return {};
+ }
+
if (proc_attr_.console.empty()) {
proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console");
}
@@ -464,13 +477,13 @@
// Configures the memory cgroup properties for the service.
void Service::ConfigureMemcg() {
if (swappiness_ != -1) {
- if (!setProcessGroupSwappiness(proc_attr_.uid, pid_, swappiness_)) {
+ if (!setProcessGroupSwappiness(uid(), pid_, swappiness_)) {
PLOG(ERROR) << "setProcessGroupSwappiness failed";
}
}
if (soft_limit_in_bytes_ != -1) {
- if (!setProcessGroupSoftLimit(proc_attr_.uid, pid_, soft_limit_in_bytes_)) {
+ if (!setProcessGroupSoftLimit(uid(), pid_, soft_limit_in_bytes_)) {
PLOG(ERROR) << "setProcessGroupSoftLimit failed";
}
}
@@ -497,7 +510,7 @@
}
if (computed_limit_in_bytes != size_t(-1)) {
- if (!setProcessGroupLimit(proc_attr_.uid, pid_, computed_limit_in_bytes)) {
+ if (!setProcessGroupLimit(uid(), pid_, computed_limit_in_bytes)) {
PLOG(ERROR) << "setProcessGroupLimit failed";
}
}
@@ -694,30 +707,28 @@
if (CgroupsAvailable()) {
bool use_memcg = swappiness_ != -1 || soft_limit_in_bytes_ != -1 || limit_in_bytes_ != -1 ||
limit_percent_ != -1 || !limit_property_.empty();
- errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
+ errno = -createProcessGroup(uid(), pid_, use_memcg);
if (errno != 0) {
Result<void> result = cgroups_activated.Write(kActivatingCgroupsFailed);
if (!result.ok()) {
return Error() << "Sending notification failed: " << result.error();
}
- return Error() << "createProcessGroup(" << proc_attr_.uid << ", " << pid_
- << ") failed for service '" << name_ << "'";
+ return Error() << "createProcessGroup(" << uid() << ", " << pid_ << ", " << use_memcg
+ << ") failed for service '" << name_ << "': " << strerror(errno);
}
// When the blkio controller is mounted in the v1 hierarchy, NormalIoPriority is
// the default (/dev/blkio). When the blkio controller is mounted in the v2 hierarchy, the
// NormalIoPriority profile has to be applied explicitly.
- SetProcessProfiles(proc_attr_.uid, pid_, {"NormalIoPriority"});
+ SetProcessProfiles(uid(), pid_, {"NormalIoPriority"});
if (use_memcg) {
ConfigureMemcg();
}
- } else {
- process_cgroup_empty_ = true;
}
if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
- LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
+ LmkdRegister(name_, uid(), pid_, oom_score_adjust_);
}
if (Result<void> result = cgroups_activated.Write(kCgroupsActivated); !result.ok()) {
@@ -755,6 +766,9 @@
NotifyStateChange("running");
reboot_on_failure.Disable();
+
+ LOG(INFO) << "... started service '" << name_ << "' has pid " << pid_;
+
return {};
}
@@ -868,6 +882,8 @@
if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) {
// An illegal flag: default to SVC_DISABLED.
+ LOG(ERROR) << "service '" << name_ << "' requested unknown flag " << how
+ << ", defaulting to disabling it.";
how = SVC_DISABLED;
}
@@ -886,6 +902,10 @@
}
if (pid_) {
+ if (flags_ & SVC_GENTLE_KILL) {
+ KillProcessGroup(SIGTERM);
+ if (!process_cgroup_empty()) std::this_thread::sleep_for(200ms);
+ }
KillProcessGroup(SIGKILL);
NotifyStateChange("stopping");
} else {
diff --git a/init/service.h b/init/service.h
index f9749d2..b858eef 100644
--- a/init/service.h
+++ b/init/service.h
@@ -19,6 +19,7 @@
#include <signal.h>
#include <sys/types.h>
+#include <algorithm>
#include <chrono>
#include <memory>
#include <optional>
@@ -56,6 +57,8 @@
// should not be killed during shutdown
#define SVC_TEMPORARY 0x1000 // This service was started by 'exec' and should be removed from the
// service list once it is reaped.
+#define SVC_GENTLE_KILL 0x2000 // This service should be stopped with SIGTERM instead of SIGKILL
+ // Will still be SIGKILLed after timeout period of 200 ms
#define NR_SVC_SUPP_GIDS 12 // twelve supplementary groups
@@ -69,7 +72,7 @@
Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
const std::string& filename, const std::vector<std::string>& args);
- Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
+ Service(const std::string& name, unsigned flags, std::optional<uid_t> uid, gid_t gid,
const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
Subcontext* subcontext_for_restart_commands, const std::string& filename,
const std::vector<std::string>& args);
@@ -113,7 +116,8 @@
pid_t pid() const { return pid_; }
android::base::boot_clock::time_point time_started() const { return time_started_; }
int crash_count() const { return crash_count_; }
- uid_t uid() const { return proc_attr_.uid; }
+ int was_last_exit_ok() const { return was_last_exit_ok_; }
+ uid_t uid() const { return proc_attr_.uid(); }
gid_t gid() const { return proc_attr_.gid; }
int namespace_flags() const { return namespaces_.flags; }
const std::vector<gid_t>& supp_gids() const { return proc_attr_.supp_gids; }
@@ -128,7 +132,15 @@
bool process_cgroup_empty() const { return process_cgroup_empty_; }
unsigned long start_order() const { return start_order_; }
void set_sigstop(bool value) { sigstop_ = value; }
- std::chrono::seconds restart_period() const { return restart_period_; }
+ std::chrono::seconds restart_period() const {
+ // If the service exited abnormally or due to timeout, late limit the restart even if
+ // restart_period is set to a very short value.
+ // If not, i.e. restart after a deliberate and successful exit, respect the period.
+ if (!was_last_exit_ok_) {
+ return std::max(restart_period_, default_restart_period_);
+ }
+ return restart_period_;
+ }
std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
const std::vector<std::string>& args() const { return args_; }
bool is_updatable() const { return updatable_; }
@@ -170,6 +182,8 @@
bool upgraded_mte_ = false; // whether we upgraded async MTE -> sync MTE before
std::chrono::minutes fatal_crash_window_ = 4min; // fatal() when more than 4 crashes in it
std::optional<std::string> fatal_reboot_target_; // reboot target of fatal handler
+ bool was_last_exit_ok_ =
+ true; // true if the service never exited, or exited with status code 0
std::optional<CapSet> capabilities_;
ProcessAttributes proc_attr_;
@@ -212,7 +226,8 @@
bool sigstop_ = false;
- std::chrono::seconds restart_period_ = 5s;
+ const std::chrono::seconds default_restart_period_ = 5s;
+ std::chrono::seconds restart_period_ = default_restart_period_;
std::optional<std::chrono::seconds> timeout_period_;
bool updatable_ = false;
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 24a2024..a1b2cc5 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -25,6 +25,7 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <hidl-util/FQName.h>
#include <processgroup/processgroup.h>
@@ -151,6 +152,11 @@
return {};
}
+Result<void> ServiceParser::ParseGentleKill(std::vector<std::string>&& args) {
+ service_->flags_ |= SVC_GENTLE_KILL;
+ return {};
+}
+
Result<void> ServiceParser::ParseGroup(std::vector<std::string>&& args) {
auto gid = DecodeUid(args[1]);
if (!gid.ok()) {
@@ -364,8 +370,8 @@
Result<void> ServiceParser::ParseRestartPeriod(std::vector<std::string>&& args) {
int period;
- if (!ParseInt(args[1], &period, 5)) {
- return Error() << "restart_period value must be an integer >= 5";
+ if (!ParseInt(args[1], &period, 0)) {
+ return Error() << "restart_period value must be an integer >= 0";
}
service_->restart_period_ = std::chrono::seconds(period);
return {};
@@ -529,7 +535,7 @@
if (!uid.ok()) {
return Error() << "Unable to find UID for '" << args[1] << "': " << uid.error();
}
- service_->proc_attr_.uid = *uid;
+ service_->proc_attr_.parsed_uid = *uid;
return {};
}
@@ -584,6 +590,7 @@
{"disabled", {0, 0, &ServiceParser::ParseDisabled}},
{"enter_namespace", {2, 2, &ServiceParser::ParseEnterNamespace}},
{"file", {2, 2, &ServiceParser::ParseFile}},
+ {"gentle_kill", {0, 0, &ServiceParser::ParseGentleKill}},
{"group", {1, NR_SVC_SUPP_GIDS + 1, &ServiceParser::ParseGroup}},
{"interface", {2, 2, &ServiceParser::ParseInterface}},
{"ioprio", {2, 2, &ServiceParser::ParseIoprio}},
@@ -671,6 +678,16 @@
return {};
}
+ if (service_->proc_attr_.parsed_uid == std::nullopt) {
+ if (android::base::GetIntProperty("ro.vendor.api_level", 0) > __ANDROID_API_U__) {
+ return Error() << "No user specified for service '" << service_->name()
+ << "'. Defaults to root.";
+ } else {
+ LOG(WARNING) << "No user specified for service '" << service_->name()
+ << "'. Defaults to root.";
+ }
+ }
+
if (interface_inheritance_hierarchy_) {
if (const auto& check_hierarchy_result = CheckInterfaceInheritanceHierarchy(
service_->interfaces(), *interface_inheritance_hierarchy_);
diff --git a/init/service_parser.h b/init/service_parser.h
index 54503dd..670a5c6 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -53,6 +53,7 @@
Result<void> ParseDisabled(std::vector<std::string>&& args);
Result<void> ParseEnterNamespace(std::vector<std::string>&& args);
Result<void> ParseGroup(std::vector<std::string>&& args);
+ Result<void> ParseGentleKill(std::vector<std::string>&& args);
Result<void> ParsePriority(std::vector<std::string>&& args);
Result<void> ParseInterface(std::vector<std::string>&& args);
Result<void> ParseIoprio(std::vector<std::string>&& args);
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index 7004d8d..0e19bcc 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -271,8 +271,8 @@
if (setgroups(attr.supp_gids.size(), const_cast<gid_t*>(&attr.supp_gids[0])) != 0) {
return ErrnoError() << "setgroups failed";
}
- if (attr.uid) {
- if (setuid(attr.uid) != 0) {
+ if (attr.uid()) {
+ if (setuid(attr.uid()) != 0) {
return ErrnoError() << "setuid failed";
}
}
diff --git a/init/service_utils.h b/init/service_utils.h
index d4143aa..27ec450 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -91,11 +91,13 @@
IoSchedClass ioprio_class;
int ioprio_pri;
std::vector<std::pair<int, rlimit>> rlimits;
- uid_t uid;
+ std::optional<uid_t> parsed_uid;
gid_t gid;
std::vector<gid_t> supp_gids;
int priority;
bool stdio_to_kmsg;
+
+ uid_t uid() const { return parsed_uid.value_or(0); }
};
inline bool RequiresConsole(const ProcessAttributes& attr) {
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 6972f30..3a9ff5b 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -112,6 +112,10 @@
setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1);
+ if (!client->RemoveTransitionedDaemonIndicator()) {
+ LOG(ERROR) << "RemoveTransitionedDaemonIndicator failed";
+ }
+
LOG(INFO) << "Relaunched snapuserd with pid: " << pid;
}
@@ -263,6 +267,19 @@
* we may see audit logs.
*/
bool SnapuserdSelinuxHelper::TestSnapuserdIsReady() {
+ // Wait for the daemon to be fully up. Daemon will write to path
+ // /metadata/ota/daemon-alive-indicator only when all the threads
+ // are ready and attached to dm-user.
+ //
+ // This check will fail for GRF devices with vendor on Android S.
+ // snapuserd binary from Android S won't be able to communicate
+ // and hence, we will fallback and issue I/O to verify
+ // the presence of daemon.
+ auto client = std::make_unique<SnapuserdClient>();
+ if (!client->IsTransitionedDaemonReady()) {
+ LOG(ERROR) << "IsTransitionedDaemonReady failed";
+ }
+
std::string dev = "/dev/block/mapper/system"s + fs_mgr_get_slot_suffix();
android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_DIRECT));
if (fd < 0) {
diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp
index 66a3328..510ad8a 100644
--- a/init/test_kill_services/init_kill_services_test.cpp
+++ b/init/test_kill_services/init_kill_services_test.cpp
@@ -16,22 +16,35 @@
#include <gtest/gtest.h>
+#include <android-base/logging.h>
#include <android-base/properties.h>
#include <iostream>
using ::android::base::GetProperty;
using ::android::base::SetProperty;
+using ::android::base::WaitForProperty;
+using std::literals::chrono_literals::operator""s;
void ExpectKillingServiceRecovers(const std::string& service_name) {
+ LOG(INFO) << "before we say hi to " << service_name << ", I can't have apexd around!";
+
+ // b/280514080 - servicemanager will restart apexd, and apexd will restart the
+ // system when crashed. This is fine as the device recovers, but it causes
+ // flakes in this test.
+ ASSERT_TRUE(WaitForProperty("init.svc.apexd", "stopped", 120s))
+ << (system("cat /dev/binderfs/binder_logs/state"), "apexd won't stop");
+
+ LOG(INFO) << "hello " << service_name << "!";
const std::string status_prop = "init.svc." + service_name;
const std::string pid_prop = "init.svc_debug_pid." + service_name;
const std::string initial_pid = GetProperty(pid_prop, "");
- EXPECT_EQ("running", GetProperty(status_prop, "")) << status_prop;
- EXPECT_NE("", initial_pid) << pid_prop;
+ ASSERT_EQ("running", GetProperty(status_prop, "")) << status_prop;
+ ASSERT_NE("", initial_pid) << pid_prop;
+ LOG(INFO) << "okay, now goodbye " << service_name;
EXPECT_EQ(0, system(("kill -9 " + initial_pid).c_str()));
constexpr size_t kMaxWaitMilliseconds = 10000;
@@ -42,11 +55,16 @@
for (size_t retry = 0; retry < kRetryTimes; retry++) {
const std::string& pid = GetProperty(pid_prop, "");
if (pid != initial_pid && pid != "") break;
+ LOG(INFO) << "I said goodbye " << service_name << "!";
usleep(kRetryWaitMilliseconds * 1000);
}
+ LOG(INFO) << "are you still there " << service_name << "?";
+
// svc_debug_pid is set after svc property
EXPECT_EQ("running", GetProperty(status_prop, ""));
+
+ LOG(INFO) << "I'm done with " << service_name;
}
class InitKillServicesTest : public ::testing::TestWithParam<std::string> {};
diff --git a/init/test_upgrade_mte/mte_upgrade_test.rc b/init/test_upgrade_mte/mte_upgrade_test.rc
index a3e596c..aa6c18f 100644
--- a/init/test_upgrade_mte/mte_upgrade_test.rc
+++ b/init/test_upgrade_mte/mte_upgrade_test.rc
@@ -16,9 +16,11 @@
class late_start
disabled
seclabel u:r:su:s0
+ user root
service mte_upgrade_test_helper_overridden /system/bin/mte_upgrade_test_helper ${sys.mte_crash_test_uuid}
class late_start
disabled
seclabel u:r:su:s0
+ user root
setenv BIONIC_MEMTAG_UPGRADE_SECS 0
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 3188337..6728cc6 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -60,6 +60,10 @@
if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
}
std::unique_ptr<volatile char[]> f(new char[1]);
+ // This out-of-bounds is on purpose: we are testing MTE, which is designed to turn
+ // out-of-bound errors into segfaults.
+ // 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);
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/libcutils/Android.bp b/libcutils/Android.bp
index b135e57..0b5c125 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -286,11 +286,14 @@
],
}
+always_static_test_libraries = [
+ "libjsoncpp",
+]
+
test_libraries = [
"libcutils",
"liblog",
"libbase",
- "libjsoncpp",
"libprocessgroup",
"libcgrouprc",
]
@@ -301,6 +304,7 @@
defaults: ["libcutils_test_default"],
host_supported: true,
shared_libs: test_libraries,
+ static_libs: always_static_test_libraries,
require_root: true,
}
@@ -310,7 +314,7 @@
static_libs: [
"libc",
"libcgrouprc_format",
- ] + test_libraries,
+ ] + test_libraries + always_static_test_libraries,
stl: "libc++_static",
require_root: true,
diff --git a/libcutils/KernelLibcutilsTest.xml b/libcutils/KernelLibcutilsTest.xml
index 40e4ef4..9750cbf 100644
--- a/libcutils/KernelLibcutilsTest.xml
+++ b/libcutils/KernelLibcutilsTest.xml
@@ -22,11 +22,11 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push" value="KernelLibcutilsTest->/data/local/tmp/KernelLibcutilsTest" />
+ <option name="push" value="KernelLibcutilsTest->/data/local/tests/unrestricted/KernelLibcutilsTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-device-path" value="/data/local/tests/unrestricted" />
<option name="module-name" value="KernelLibcutilsTest" />
<option name="include-filter" value="*AshmemTest*" />
</test>
diff --git a/libcutils/TEST_MAPPING b/libcutils/TEST_MAPPING
index 6477502..78b3e44 100644
--- a/libcutils/TEST_MAPPING
+++ b/libcutils/TEST_MAPPING
@@ -8,5 +8,13 @@
{
"name": "libcutils_test"
}
+ ],
+ "kernel-presubmit": [
+ {
+ "name": "libcutils_test"
+ },
+ {
+ "name": "KernelLibcutilsTest"
+ }
]
}
diff --git a/libcutils/ashmem_test.cpp b/libcutils/ashmem_test.cpp
index fb657f6..d158427 100644
--- a/libcutils/ashmem_test.cpp
+++ b/libcutils/ashmem_test.cpp
@@ -75,7 +75,7 @@
unique_fd fd;
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
- void *region1;
+ void* region1 = nullptr;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, ®ion1));
memcpy(region1, &data, size);
@@ -97,7 +97,7 @@
unique_fd fd;
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
- void *region1;
+ void* region1 = nullptr;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, ®ion1));
memcpy(region1, &data, size);
@@ -131,7 +131,7 @@
TEST(AshmemTest, FileOperationsTest) {
unique_fd fd;
- void* region;
+ void* region = nullptr;
// Allocate a 4-page buffer, but leave page-sized holes on either side
constexpr size_t size = PAGE_SIZE * 4;
@@ -246,7 +246,7 @@
unique_fd fd[nRegions];
for (int i = 0; i < nRegions; i++) {
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd[i], PROT_READ | PROT_WRITE));
- void *region;
+ void* region = nullptr;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, ®ion));
memcpy(region, &data, size);
ASSERT_EQ(0, memcmp(region, &data, size));
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index a6835fc..f90a1bc 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -83,11 +83,13 @@
{ 00751, AID_ROOT, AID_SHELL, 0, "product/apex/*/bin" },
{ 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
{ 00751, AID_ROOT, AID_SDCARD_R, 0, "storage" },
+ { 00750, AID_ROOT, AID_SYSTEM, 0, "system/apex/com.android.tethering/bin/for-system" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system/bin" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
{ 00750, AID_ROOT, AID_SHELL, 0, "system/xbin" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin" },
+ { 00750, AID_ROOT, AID_SYSTEM, 0, "system_ext/apex/com.android.tethering/bin/for-system" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system_ext/bin" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system_ext/apex/*/bin" },
{ 00751, AID_ROOT, AID_SHELL, 0, "vendor/bin" },
@@ -194,6 +196,8 @@
// the following files have enhanced capabilities and ARE included
// in user builds.
+ { 06755, AID_CLAT, AID_CLAT, 0, "system/apex/com.android.tethering/bin/for-system/clatd" },
+ { 06755, AID_CLAT, AID_CLAT, 0, "system_ext/apex/com.android.tethering/bin/for-system/clatd" },
{ 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
"system/bin/inputflinger" },
{ 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) |
diff --git a/libcutils/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
index a5ffb03..8902c2b 100644
--- a/libcutils/include/cutils/qtaguid.h
+++ b/libcutils/include/cutils/qtaguid.h
@@ -33,12 +33,6 @@
*/
extern int qtaguid_untagSocket(int sockfd);
-/*
- * Enable/disable qtaguid functionnality at a lower level.
- * When pacified, the kernel will accept commands but do nothing.
- */
-extern int qtaguid_setPacifier(int on);
-
#ifdef __cplusplus
}
#endif
diff --git a/libcutils/qtaguid.cpp b/libcutils/qtaguid.cpp
index a987b85..f847782 100644
--- a/libcutils/qtaguid.cpp
+++ b/libcutils/qtaguid.cpp
@@ -22,76 +22,60 @@
#include <dlfcn.h>
#include <errno.h>
-#include <fcntl.h>
#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
#include <log/log.h>
-class netdHandler {
- public:
+struct netdHandler {
int (*netdTagSocket)(int, uint32_t, uid_t);
int (*netdUntagSocket)(int);
};
-int stubTagSocket(int, uint32_t, uid_t) {
+static int stubTagSocket(int, uint32_t, uid_t) {
return -EREMOTEIO;
}
-int stubUntagSocket(int) {
+static int stubUntagSocket(int) {
return -EREMOTEIO;
}
-netdHandler initHandler(void) {
- netdHandler handler = {stubTagSocket, stubUntagSocket};
+static netdHandler initHandler(void) {
+ const netdHandler stubHandler = { stubTagSocket, stubUntagSocket };
void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
if (!netdClientHandle) {
ALOGE("Failed to open libnetd_client.so: %s", dlerror());
- return handler;
+ return stubHandler;
}
+ netdHandler handler;
handler.netdTagSocket = (int (*)(int, uint32_t, uid_t))dlsym(netdClientHandle, "tagSocket");
if (!handler.netdTagSocket) {
ALOGE("load netdTagSocket handler failed: %s", dlerror());
+ return stubHandler;
}
handler.netdUntagSocket = (int (*)(int))dlsym(netdClientHandle, "untagSocket");
if (!handler.netdUntagSocket) {
ALOGE("load netdUntagSocket handler failed: %s", dlerror());
+ return stubHandler;
}
return handler;
}
// The language guarantees that this object will be initialized in a thread-safe way.
-static netdHandler& getHandler() {
- static netdHandler instance = initHandler();
+static const netdHandler& getHandler() {
+ static const netdHandler instance = initHandler();
return instance;
}
int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
- // Check the socket fd passed to us is still valid before we load the netd
- // client. Pass a already closed socket fd to netd client may let netd open
- // the unix socket with the same fd number and pass it to server for
- // tagging.
- // TODO: move the check into netdTagSocket.
- int res = fcntl(sockfd, F_GETFD);
- if (res < 0) return res;
-
ALOGV("Tagging socket %d with tag %u for uid %d", sockfd, tag, uid);
return getHandler().netdTagSocket(sockfd, tag, uid);
}
int qtaguid_untagSocket(int sockfd) {
- // Similiar to tag socket. We need a check before untag to make sure untag a closed socket fail
- // as expected.
- // TODO: move the check into netdTagSocket.
- int res = fcntl(sockfd, F_GETFD);
- if (res < 0) return res;
-
ALOGV("Untagging socket %d", sockfd);
return getHandler().netdUntagSocket(sockfd);
}
diff --git a/libcutils/sched_policy_test.cpp b/libcutils/sched_policy_test.cpp
index b9e2832..50bd6d0 100644
--- a/libcutils/sched_policy_test.cpp
+++ b/libcutils/sched_policy_test.cpp
@@ -75,9 +75,11 @@
}
ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+ ASSERT_EQ(0, set_cpuset_policy(0, SP_BACKGROUND));
AssertPolicy(SP_BACKGROUND);
ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+ ASSERT_EQ(0, set_cpuset_policy(0, SP_FOREGROUND));
AssertPolicy(SP_FOREGROUND);
}
diff --git a/libdiskconfig/Android.bp b/libdiskconfig/Android.bp
deleted file mode 100644
index f523d4e..0000000
--- a/libdiskconfig/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libdiskconfig",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- srcs: [
- "diskconfig.c",
- "diskutils.c",
- "write_lst.c",
- "config_mbr.c",
- ],
-
- shared_libs: [
- "libcutils",
- "liblog",
- ],
- cflags: ["-Werror"],
- export_include_dirs: ["include"],
- local_include_dirs: ["include"],
-
- target: {
- darwin: {
- enabled: false,
- },
- host_linux: {
- cflags: [
- "-D_LARGEFILE64_SOURCE",
- ],
- },
- },
-}
diff --git a/libdiskconfig/config_mbr.c b/libdiskconfig/config_mbr.c
deleted file mode 100644
index ace9bbf..0000000
--- a/libdiskconfig/config_mbr.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/* libs/diskconfig/diskconfig.c
- *
- * Copyright 2008, 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.
- */
-
-#define LOG_TAG "config_mbr"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <diskconfig/diskconfig.h>
-#include <log/log.h>
-
-/* start and len are in LBA units */
-static void
-cfg_pentry(struct pc_partition *pentry, uint8_t status, uint8_t type,
- uint32_t start, uint32_t len)
-{
- if (len > 0) {
- /* seems that somes BIOSens can get wedged on boot while verifying
- * the mbr if these are 0 */
- memset(&pentry->start, 0xff, sizeof(struct chs));
- memset(&pentry->end, 0xff, sizeof(struct chs));
- } else {
- /* zero out the c/h/s entries.. they are not used */
- memset(&pentry->start, 0, sizeof(struct chs));
- memset(&pentry->end, 0, sizeof(struct chs));
- }
-
- pentry->status = status;
- pentry->type = type;
- pentry->start_lba = start;
- pentry->len_lba = len;
-
- ALOGI("Configuring pentry. status=0x%x type=0x%x start_lba=%u len_lba=%u",
- pentry->status, pentry->type, pentry->start_lba, pentry->len_lba);
-}
-
-
-static inline uint32_t
-kb_to_lba(uint32_t len_kb, uint32_t sect_size)
-{
- uint64_t lba;
-
- lba = (uint64_t)len_kb * 1024;
- /* bump it up to the next LBA boundary just in case */
- lba = (lba + (uint64_t)sect_size - 1) & ~((uint64_t)sect_size - 1);
- lba /= (uint64_t)sect_size;
- if (lba >= 0xffffffffULL)
- ALOGE("Error converting kb -> lba. 32bit overflow, expect weirdness");
- return (uint32_t)(lba & 0xffffffffULL);
-}
-
-
-static struct write_list *
-mk_pri_pentry(struct disk_info *dinfo, struct part_info *pinfo, int pnum,
- uint32_t *lba)
-{
- struct write_list *item;
- struct pc_partition *pentry;
-
- if (pnum >= PC_NUM_BOOT_RECORD_PARTS) {
- ALOGE("Maximum number of primary partition exceeded.");
- return NULL;
- }
-
- if (!(item = alloc_wl(sizeof(struct pc_partition)))) {
- ALOGE("Unable to allocate memory for partition entry.");
- return NULL;
- }
-
- {
- /* DO NOT DEREFERENCE */
- struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET;
- /* grab the offset in mbr where to write this partition entry. */
- item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->ptable[pnum])));
- }
-
- pentry = (struct pc_partition *) &item->data;
-
- /* need a standard primary partition entry */
- if (pinfo) {
- /* need this to be 64 bit in case len_kb is large */
- uint64_t len_lba;
-
- if (pinfo->len_kb != (uint32_t)-1) {
- /* bump it up to the next LBA boundary just in case */
- len_lba = ((uint64_t)pinfo->len_kb * 1024);
- len_lba += ((uint64_t)dinfo->sect_size - 1);
- len_lba &= ~((uint64_t)dinfo->sect_size - 1);
- len_lba /= (uint64_t)dinfo->sect_size;
- } else {
- /* make it fill the rest of disk */
- len_lba = dinfo->num_lba - *lba;
- }
-
- cfg_pentry(pentry, ((pinfo->flags & PART_ACTIVE_FLAG) ?
- PC_PART_ACTIVE : PC_PART_NORMAL),
- pinfo->type, *lba, (uint32_t)len_lba);
-
- pinfo->start_lba = *lba;
- *lba += (uint32_t)len_lba;
- } else {
- /* this should be made an extended partition, and should take
- * up the rest of the disk as a primary partition */
- cfg_pentry(pentry, PC_PART_NORMAL, PC_PART_TYPE_EXTENDED,
- *lba, dinfo->num_lba - *lba);
-
- /* note that we do not update the *lba because we now have to
- * create a chain of extended partition tables, and first one is at
- * *lba */
- }
-
- return item;
-}
-
-
-/* This function configures an extended boot record at the beginning of an
- * extended partition. This creates a logical partition and a pointer to
- * the next EBR.
- *
- * ext_lba == The start of the toplevel extended partition (pointed to by the
- * entry in the MBR).
- */
-static struct write_list *
-mk_ext_pentry(struct disk_info *dinfo, struct part_info *pinfo, uint32_t *lba,
- uint32_t ext_lba, struct part_info *pnext)
-{
- struct write_list *item;
- struct pc_boot_record *ebr;
- uint32_t len; /* in lba units */
-
- if (!(item = alloc_wl(sizeof(struct pc_boot_record)))) {
- ALOGE("Unable to allocate memory for EBR.");
- return NULL;
- }
-
- /* we are going to write the ebr at the current LBA, and then bump the
- * lba counter since that is where the logical data partition will start */
- item->offset = ((loff_t)(*lba)) * dinfo->sect_size;
- (*lba)++;
-
- ebr = (struct pc_boot_record *) &item->data;
- memset(ebr, 0, sizeof(struct pc_boot_record));
- ebr->mbr_sig = PC_BIOS_BOOT_SIG;
-
- if (pinfo->len_kb != (uint32_t)-1)
- len = kb_to_lba(pinfo->len_kb, dinfo->sect_size);
- else {
- if (pnext) {
- ALOGE("Only the last partition can be specified to fill the disk "
- "(name = '%s')", pinfo->name);
- goto fail;
- }
- len = dinfo->num_lba - *lba;
- /* update the pinfo structure to reflect the new size, for
- * bookkeeping */
- pinfo->len_kb =
- (uint32_t)(((uint64_t)len * (uint64_t)dinfo->sect_size) /
- ((uint64_t)1024));
- }
-
- cfg_pentry(&ebr->ptable[PC_EBR_LOGICAL_PART], PC_PART_NORMAL,
- pinfo->type, 1, len);
-
- pinfo->start_lba = *lba;
- *lba += len;
-
- /* If this is not the last partition, we have to create a link to the
- * next extended partition.
- *
- * Otherwise, there's nothing to do since the "pointer entry" is
- * already zero-filled.
- */
- if (pnext) {
- /* The start lba for next partition is an offset from the beginning
- * of the top-level extended partition */
- uint32_t next_start_lba = *lba - ext_lba;
- uint32_t next_len_lba;
- if (pnext->len_kb != (uint32_t)-1)
- next_len_lba = 1 + kb_to_lba(pnext->len_kb, dinfo->sect_size);
- else
- next_len_lba = dinfo->num_lba - *lba;
- cfg_pentry(&ebr->ptable[PC_EBR_NEXT_PTR_PART], PC_PART_NORMAL,
- PC_PART_TYPE_EXTENDED, next_start_lba, next_len_lba);
- }
-
- return item;
-
-fail:
- free_wl(item);
- return NULL;
-}
-
-
-static struct write_list *
-mk_mbr_sig()
-{
- struct write_list *item;
- if (!(item = alloc_wl(sizeof(uint16_t)))) {
- ALOGE("Unable to allocate memory for MBR signature.");
- return NULL;
- }
-
- {
- /* DO NOT DEREFERENCE */
- struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET;
- /* grab the offset in mbr where to write mbr signature. */
- item->offset = (loff_t)((uintptr_t)((uint8_t *)(&mbr->mbr_sig)));
- }
-
- *((uint16_t*)item->data) = PC_BIOS_BOOT_SIG;
- return item;
-}
-
-struct write_list *
-config_mbr(struct disk_info *dinfo)
-{
- struct part_info *pinfo;
- uint32_t cur_lba = dinfo->skip_lba;
- uint32_t ext_lba = 0;
- struct write_list *wr_list = NULL;
- struct write_list *temp_wr = NULL;
- int cnt = 0;
- int extended = 0;
-
- if (!dinfo->part_lst)
- return NULL;
-
- for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
- pinfo = &dinfo->part_lst[cnt];
-
- /* Should we create an extedned partition? */
- if (cnt == (PC_NUM_BOOT_RECORD_PARTS - 1)) {
- if (cnt + 1 < dinfo->num_parts) {
- extended = 1;
- ext_lba = cur_lba;
- if ((temp_wr = mk_pri_pentry(dinfo, NULL, cnt, &cur_lba)))
- wlist_add(&wr_list, temp_wr);
- else {
- ALOGE("Cannot create primary extended partition.");
- goto fail;
- }
- }
- }
-
- /* if extended, need 1 lba for ebr */
- if ((cur_lba + extended) >= dinfo->num_lba)
- goto nospace;
- else if (pinfo->len_kb != (uint32_t)-1) {
- uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024;
- if ((cur_lba + sz_lba + extended) > dinfo->num_lba)
- goto nospace;
- }
-
- if (!extended)
- temp_wr = mk_pri_pentry(dinfo, pinfo, cnt, &cur_lba);
- else {
- struct part_info *pnext;
- pnext = cnt + 1 < dinfo->num_parts ? &dinfo->part_lst[cnt+1] : NULL;
- temp_wr = mk_ext_pentry(dinfo, pinfo, &cur_lba, ext_lba, pnext);
- }
-
- if (temp_wr)
- wlist_add(&wr_list, temp_wr);
- else {
- ALOGE("Cannot create partition %d (%s).", cnt, pinfo->name);
- goto fail;
- }
- }
-
- /* fill in the rest of the MBR with empty parts (if needed). */
- for (; cnt < PC_NUM_BOOT_RECORD_PARTS; ++cnt) {
- struct part_info blank;
- cur_lba = 0;
- memset(&blank, 0, sizeof(struct part_info));
- if (!(temp_wr = mk_pri_pentry(dinfo, &blank, cnt, &cur_lba))) {
- ALOGE("Cannot create blank partition %d.", cnt);
- goto fail;
- }
- wlist_add(&wr_list, temp_wr);
- }
-
- if ((temp_wr = mk_mbr_sig()))
- wlist_add(&wr_list, temp_wr);
- else {
- ALOGE("Cannot set MBR signature");
- goto fail;
- }
-
- return wr_list;
-
-nospace:
- ALOGE("Not enough space to add parttion '%s'.", pinfo->name);
-
-fail:
- wlist_free(wr_list);
- return NULL;
-}
-
-
-/* Returns the device path of the partition referred to by 'name'
- * Must be freed by the caller.
- */
-char *
-find_mbr_part(struct disk_info *dinfo, const char *name)
-{
- struct part_info *plist = dinfo->part_lst;
- int num = 0;
- char *dev_name = NULL;
- int has_extended = (dinfo->num_parts > PC_NUM_BOOT_RECORD_PARTS);
-
- for(num = 1; num <= dinfo->num_parts; ++num) {
- if (!strcmp(plist[num-1].name, name))
- break;
- }
-
- if (num > dinfo->num_parts)
- return NULL;
-
- if (has_extended && (num >= PC_NUM_BOOT_RECORD_PARTS))
- num++;
-
- if (!(dev_name = malloc(MAX_NAME_LEN))) {
- ALOGE("Cannot allocate memory.");
- return NULL;
- }
-
- num = snprintf(dev_name, MAX_NAME_LEN, "%s%d", dinfo->device, num);
- if (num >= MAX_NAME_LEN) {
- ALOGE("Device name is too long?!");
- free(dev_name);
- return NULL;
- }
-
- return dev_name;
-}
diff --git a/libdiskconfig/diskconfig.c b/libdiskconfig/diskconfig.c
deleted file mode 100644
index c7e1b43..0000000
--- a/libdiskconfig/diskconfig.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/* libs/diskconfig/diskconfig.c
- *
- * Copyright 2008, 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.
- */
-
-#define LOG_TAG "diskconfig"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <linux/fs.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <cutils/config_utils.h>
-#include <log/log.h>
-
-#include <diskconfig/diskconfig.h>
-
-static int
-parse_len(const char *str, uint64_t *plen)
-{
- char tmp[64];
- int len_str;
- uint32_t multiple = 1;
-
- strncpy(tmp, str, sizeof(tmp));
- tmp[sizeof(tmp)-1] = '\0';
- len_str = strlen(tmp);
- if (!len_str) {
- ALOGE("Invalid disk length specified.");
- return 1;
- }
-
- switch(tmp[len_str - 1]) {
- case 'M': case 'm':
- /* megabyte */
- multiple <<= 10;
- case 'K': case 'k':
- /* kilobytes */
- multiple <<= 10;
- tmp[len_str - 1] = '\0';
- break;
- default:
- break;
- }
-
- *plen = strtoull(tmp, NULL, 0);
- if (!*plen) {
- ALOGE("Invalid length specified: %s", str);
- return 1;
- }
-
- if (*plen == (uint64_t)-1) {
- if (multiple > 1) {
- ALOGE("Size modifier illegal when len is -1");
- return 1;
- }
- } else {
- /* convert len to kilobytes */
- if (multiple > 1024)
- multiple >>= 10;
- *plen *= multiple;
-
- if (*plen > 0xffffffffULL) {
- ALOGE("Length specified is too large!: %"PRIu64" KB", *plen);
- return 1;
- }
- }
-
- return 0;
-}
-
-
-static int
-load_partitions(cnode *root, struct disk_info *dinfo)
-{
- cnode *partnode;
-
- dinfo->num_parts = 0;
- for (partnode = root->first_child; partnode; partnode = partnode->next) {
- struct part_info *pinfo = &dinfo->part_lst[dinfo->num_parts];
- const char *tmp;
-
- /* bleh, i will leak memory here, but i DONT CARE since
- * the only right thing to do when this function fails
- * is to quit */
- pinfo->name = strdup(partnode->name);
-
- if(config_bool(partnode, "active", 0))
- pinfo->flags |= PART_ACTIVE_FLAG;
-
- if (!(tmp = config_str(partnode, "type", NULL))) {
- ALOGE("Partition type required: %s", pinfo->name);
- return 1;
- }
-
- /* possible values are: linux, fat32 */
- if (!strcmp(tmp, "linux")) {
- pinfo->type = PC_PART_TYPE_LINUX;
- } else if (!strcmp(tmp, "fat32")) {
- pinfo->type = PC_PART_TYPE_FAT32;
- } else {
- ALOGE("Unsupported partition type found: %s", tmp);
- return 1;
- }
-
- if ((tmp = config_str(partnode, "len", NULL)) != NULL) {
- uint64_t len;
- if (parse_len(tmp, &len))
- return 1;
- pinfo->len_kb = (uint32_t) len;
- } else
- pinfo->len_kb = 0;
-
- ++dinfo->num_parts;
- }
-
- return 0;
-}
-
-struct disk_info *
-load_diskconfig(const char *fn, char *path_override)
-{
- struct disk_info *dinfo;
- cnode *devroot;
- cnode *partnode;
- cnode *root = config_node("", "");
- const char *tmp;
-
- if (!(dinfo = malloc(sizeof(struct disk_info)))) {
- ALOGE("Could not malloc disk_info");
- return NULL;
- }
- memset(dinfo, 0, sizeof(struct disk_info));
-
- if (!(dinfo->part_lst = malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {
- ALOGE("Could not malloc part_lst");
- goto fail;
- }
- memset(dinfo->part_lst, 0,
- (MAX_NUM_PARTS * sizeof(struct part_info)));
-
- config_load_file(root, fn);
- if (root->first_child == NULL) {
- ALOGE("Could not read config file %s", fn);
- goto fail;
- }
-
- if (!(devroot = config_find(root, "device"))) {
- ALOGE("Could not find device section in config file '%s'", fn);
- goto fail;
- }
-
-
- if (!(tmp = config_str(devroot, "path", path_override))) {
- ALOGE("device path is requried");
- goto fail;
- }
- dinfo->device = strdup(tmp);
-
- /* find the partition scheme */
- if (!(tmp = config_str(devroot, "scheme", NULL))) {
- ALOGE("partition scheme is required");
- goto fail;
- } else if (!strcmp(tmp, "mbr")) {
- dinfo->scheme = PART_SCHEME_MBR;
- } else if (!strcmp(tmp, "gpt")) {
- ALOGE("'gpt' partition scheme not supported yet.");
- goto fail;
- } else {
- ALOGE("Unknown partition scheme specified: %s", tmp);
- goto fail;
- }
-
- /* grab the sector size (in bytes) */
- tmp = config_str(devroot, "sector_size", "512");
- dinfo->sect_size = strtol(tmp, NULL, 0);
- if (!dinfo->sect_size) {
- ALOGE("Invalid sector size: %s", tmp);
- goto fail;
- }
-
- /* first lba where the partitions will start on disk */
- if (!(tmp = config_str(devroot, "start_lba", NULL))) {
- ALOGE("start_lba must be provided");
- goto fail;
- }
-
- if (!(dinfo->skip_lba = strtol(tmp, NULL, 0))) {
- ALOGE("Invalid starting LBA (or zero): %s", tmp);
- goto fail;
- }
-
- /* Number of LBAs on disk */
- if (!(tmp = config_str(devroot, "num_lba", NULL))) {
- ALOGE("num_lba is required");
- goto fail;
- }
- dinfo->num_lba = strtoul(tmp, NULL, 0);
-
- if (!(partnode = config_find(devroot, "partitions"))) {
- ALOGE("Device must specify partition list");
- goto fail;
- }
-
- if (load_partitions(partnode, dinfo))
- goto fail;
-
- return dinfo;
-
-fail:
- if (dinfo->part_lst)
- free(dinfo->part_lst);
- if (dinfo->device)
- free(dinfo->device);
- free(dinfo);
- return NULL;
-}
-
-static int
-sync_ptable(int fd)
-{
- struct stat stat;
- int rv;
-
- sync();
-
- if (fstat(fd, &stat)) {
- ALOGE("Cannot stat, errno=%d.", errno);
- return -1;
- }
-
- if (S_ISBLK(stat.st_mode) && ((rv = ioctl(fd, BLKRRPART, NULL)) < 0)) {
- ALOGE("Could not re-read partition table. REBOOT!. (errno=%d)", errno);
- return -1;
- }
-
- return 0;
-}
-
-/* This function verifies that the disk info provided is valid, and if so,
- * returns an open file descriptor.
- *
- * This does not necessarily mean that it will later be successfully written
- * though. If we use the pc-bios partitioning scheme, we must use extended
- * partitions, which eat up some hd space. If the user manually provisioned
- * every single partition, but did not account for the extra needed space,
- * then we will later fail.
- *
- * TODO: Make validation more complete.
- */
-static int
-validate(struct disk_info *dinfo)
-{
- int fd;
- int sect_sz;
- uint64_t disk_size;
- uint64_t total_size;
- int cnt;
- struct stat stat;
-
- if (!dinfo)
- return -1;
-
- if ((fd = open(dinfo->device, O_RDWR)) < 0) {
- ALOGE("Cannot open device '%s' (errno=%d)", dinfo->device, errno);
- return -1;
- }
-
- if (fstat(fd, &stat)) {
- ALOGE("Cannot stat file '%s', errno=%d.", dinfo->device, errno);
- goto fail;
- }
-
-
- /* XXX: Some of the code below is kind of redundant and should probably
- * be refactored a little, but it will do for now. */
-
- /* Verify that we can operate on the device that was requested.
- * We presently only support block devices and regular file images. */
- if (S_ISBLK(stat.st_mode)) {
- /* get the sector size and make sure we agree */
- if (ioctl(fd, BLKSSZGET, §_sz) < 0) {
- ALOGE("Cannot get sector size (errno=%d)", errno);
- goto fail;
- }
-
- if (!sect_sz || sect_sz != dinfo->sect_size) {
- ALOGE("Device sector size is zero or sector sizes do not match!");
- goto fail;
- }
-
- /* allow the user override the "disk size" if they provided num_lba */
- if (!dinfo->num_lba) {
- if (ioctl(fd, BLKGETSIZE64, &disk_size) < 0) {
- ALOGE("Could not get block device size (errno=%d)", errno);
- goto fail;
- }
- /* XXX: we assume that the disk has < 2^32 sectors :-) */
- dinfo->num_lba = (uint32_t)(disk_size / (uint64_t)dinfo->sect_size);
- } else
- disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size;
- } else if (S_ISREG(stat.st_mode)) {
- ALOGI("Requesting operation on a regular file, not block device.");
- if (!dinfo->sect_size) {
- ALOGE("Sector size for regular file images cannot be zero");
- goto fail;
- }
- if (dinfo->num_lba)
- disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size;
- else {
- dinfo->num_lba = (uint32_t)(stat.st_size / dinfo->sect_size);
- disk_size = (uint64_t)stat.st_size;
- }
- } else {
- ALOGE("Device does not refer to a regular file or a block device!");
- goto fail;
- }
-
-#if 1
- ALOGV("Device/file %s: size=%" PRIu64 " bytes, num_lba=%u, sect_size=%d",
- dinfo->device, disk_size, dinfo->num_lba, dinfo->sect_size);
-#endif
-
- /* since this is our offset into the disk, we start off with that as
- * our size of needed partitions */
- total_size = dinfo->skip_lba * dinfo->sect_size;
-
- /* add up all the partition sizes and make sure it fits */
- for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
- struct part_info *part = &dinfo->part_lst[cnt];
- if (part->len_kb != (uint32_t)-1) {
- total_size += part->len_kb * 1024;
- } else if (part->len_kb == 0) {
- ALOGE("Zero-size partition '%s' is invalid.", part->name);
- goto fail;
- } else {
- /* the partition requests the rest of the disk. */
- if (cnt + 1 != dinfo->num_parts) {
- ALOGE("Only the last partition in the list can request to fill "
- "the rest of disk.");
- goto fail;
- }
- }
-
- if ((part->type != PC_PART_TYPE_LINUX) &&
- (part->type != PC_PART_TYPE_FAT32)) {
- ALOGE("Unknown partition type (0x%x) encountered for partition "
- "'%s'\n", part->type, part->name);
- goto fail;
- }
- }
-
- /* only matters for disks, not files */
- if (S_ISBLK(stat.st_mode) && total_size > disk_size) {
- ALOGE("Total requested size of partitions (%"PRIu64") is greater than disk "
- "size (%"PRIu64").", total_size, disk_size);
- goto fail;
- }
-
- return fd;
-
-fail:
- close(fd);
- return -1;
-}
-
-static int
-validate_and_config(struct disk_info *dinfo, int *fd, struct write_list **lst)
-{
- *lst = NULL;
- *fd = -1;
-
- if ((*fd = validate(dinfo)) < 0)
- return 1;
-
- switch (dinfo->scheme) {
- case PART_SCHEME_MBR:
- *lst = config_mbr(dinfo);
- return *lst == NULL;
- case PART_SCHEME_GPT:
- /* not supported yet */
- default:
- ALOGE("Uknown partition scheme.");
- break;
- }
-
- close(*fd);
- *lst = NULL;
- return 1;
-}
-
-/* validate and process the disk layout configuration.
- * This will cause an update to the partitions' start lba.
- *
- * Basically, this does the same thing as apply_disk_config in test mode,
- * except that wlist_commit is not called to print out the data to be
- * written.
- */
-int
-process_disk_config(struct disk_info *dinfo)
-{
- struct write_list *lst;
- int fd;
-
- if (validate_and_config(dinfo, &fd, &lst) != 0)
- return 1;
-
- close(fd);
- wlist_free(lst);
- return 0;
-}
-
-
-int
-apply_disk_config(struct disk_info *dinfo, int test)
-{
- int fd;
- struct write_list *wr_lst = NULL;
- int rv;
-
- if (validate_and_config(dinfo, &fd, &wr_lst) != 0) {
- ALOGE("Configuration is invalid.");
- goto fail;
- }
-
- if ((rv = wlist_commit(fd, wr_lst, test)) >= 0)
- rv = test ? 0 : sync_ptable(fd);
-
- close(fd);
- wlist_free(wr_lst);
- return rv;
-
-fail:
- close(fd);
- if (wr_lst)
- wlist_free(wr_lst);
- return 1;
-}
-
-int
-dump_disk_config(struct disk_info *dinfo)
-{
- int cnt;
- struct part_info *part;
-
- printf("Device: %s\n", dinfo->device);
- printf("Scheme: ");
- switch (dinfo->scheme) {
- case PART_SCHEME_MBR:
- printf("MBR");
- break;
- case PART_SCHEME_GPT:
- printf("GPT (unsupported)");
- break;
- default:
- printf("Unknown");
- break;
- }
- printf ("\n");
-
- printf("Sector size: %d\n", dinfo->sect_size);
- printf("Skip leading LBAs: %u\n", dinfo->skip_lba);
- printf("Number of LBAs: %u\n", dinfo->num_lba);
- printf("Partitions:\n");
-
- for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
- part = &dinfo->part_lst[cnt];
- printf("\tname = %s\n", part->name);
- printf("\t\tflags = %s\n",
- part->flags & PART_ACTIVE_FLAG ? "Active" : "None");
- printf("\t\ttype = %s\n",
- part->type == PC_PART_TYPE_LINUX ? "Linux" : "Unknown");
- if (part->len_kb == (uint32_t)-1)
- printf("\t\tlen = rest of disk\n");
- else
- printf("\t\tlen = %uKB\n", part->len_kb);
- }
- printf("Total number of partitions: %d\n", cnt);
- printf("\n");
-
- return 0;
-}
-
-struct part_info *
-find_part(struct disk_info *dinfo, const char *name)
-{
- struct part_info *pinfo;
- int cnt;
-
- for (cnt = 0; cnt < dinfo->num_parts; ++cnt) {
- pinfo = &dinfo->part_lst[cnt];
- if (!strcmp(pinfo->name, name))
- return pinfo;
- }
-
- return NULL;
-}
-
-/* NOTE: If the returned ptr is non-NULL, it must be freed by the caller. */
-char *
-find_part_device(struct disk_info *dinfo, const char *name)
-{
- switch (dinfo->scheme) {
- case PART_SCHEME_MBR:
- return find_mbr_part(dinfo, name);
- case PART_SCHEME_GPT:
- ALOGE("GPT is presently not supported");
- break;
- default:
- ALOGE("Unknown partition table scheme");
- break;
- }
-
- return NULL;
-}
-
-
diff --git a/libdiskconfig/diskutils.c b/libdiskconfig/diskutils.c
deleted file mode 100644
index fe1b4c1..0000000
--- a/libdiskconfig/diskutils.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* libs/diskconfig/diskutils.c
- *
- * Copyright 2008, 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.
- */
-
-#define LOG_TAG "diskutils"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include <diskconfig/diskconfig.h>
-
-int
-write_raw_image(const char *dst, const char *src, loff_t offset, int test)
-{
- int dst_fd = -1;
- int src_fd = -1;
- uint8_t buffer[2048];
- ssize_t nr_bytes;
- ssize_t tmp;
- int done = 0;
- uint64_t total = 0;
-
- ALOGI("Writing RAW image '%s' to '%s' (offset=%llu)", src, dst, (unsigned long long)offset);
- if ((src_fd = open(src, O_RDONLY)) < 0) {
- ALOGE("Could not open %s for reading (errno=%d).", src, errno);
- goto fail;
- }
-
- if (!test) {
- if ((dst_fd = open(dst, O_RDWR)) < 0) {
- ALOGE("Could not open '%s' for read/write (errno=%d).", dst, errno);
- goto fail;
- }
-
- if (lseek64(dst_fd, offset, SEEK_SET) != offset) {
- ALOGE("Could not seek to offset %lld in %s.", (long long)offset, dst);
- goto fail;
- }
- }
-
- while (!done) {
- if ((nr_bytes = read(src_fd, buffer, sizeof(buffer))) < 0) {
- /* XXX: Should we not even bother with EINTR? */
- if (errno == EINTR)
- continue;
- ALOGE("Error (%d) while reading from '%s'", errno, src);
- goto fail;
- }
-
- if (!nr_bytes) {
- /* we're done. */
- done = 1;
- break;
- }
-
- total += nr_bytes;
-
- /* skip the write loop if we're testing */
- if (test)
- nr_bytes = 0;
-
- while (nr_bytes > 0) {
- if ((tmp = write(dst_fd, buffer, nr_bytes)) < 0) {
- /* XXX: Should we not even bother with EINTR? */
- if (errno == EINTR)
- continue;
- ALOGE("Error (%d) while writing to '%s'", errno, dst);
- goto fail;
- }
- if (!tmp)
- continue;
- nr_bytes -= tmp;
- }
- }
-
- if (!done) {
- ALOGE("Exited read/write loop without setting flag! WTF?!");
- goto fail;
- }
-
- if (dst_fd >= 0)
- fsync(dst_fd);
-
- ALOGI("Wrote %" PRIu64 " bytes to %s @ %lld", total, dst, (long long)offset);
-
- close(src_fd);
- if (dst_fd >= 0)
- close(dst_fd);
- return 0;
-
-fail:
- if (dst_fd >= 0)
- close(dst_fd);
- if (src_fd >= 0)
- close(src_fd);
- return 1;
-}
diff --git a/libdiskconfig/dump_diskconfig.c b/libdiskconfig/dump_diskconfig.c
deleted file mode 100644
index 3c4f620..0000000
--- a/libdiskconfig/dump_diskconfig.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* libs/diskconfig/dump_diskconfig.c
- *
- * Copyright 2008, 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.
- */
-
-#define LOG_TAG "dump_diskconfig"
-
-#include <stdio.h>
-
-#include <log/log.h>
-
-#include "diskconfig.h"
-
-int
-main(int argc, char *argv[])
-{
- struct disk_info *dinfo;
-
- if (argc < 2) {
- ALOGE("usage: %s <conf file>", argv[0]);
- return 1;
- }
-
- if (!(dinfo = load_diskconfig(argv[1], NULL)))
- return 1;
-
- dump_disk_config(dinfo);
-
- return 0;
-}
-
diff --git a/libdiskconfig/include/diskconfig/diskconfig.h b/libdiskconfig/include/diskconfig/diskconfig.h
deleted file mode 100644
index d45b99e..0000000
--- a/libdiskconfig/include/diskconfig/diskconfig.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* system/core/include/diskconfig/diskconfig.h
- *
- * Copyright 2008, 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 __LIBS_DISKCONFIG_H
-#define __LIBS_DISKCONFIG_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MAX_NAME_LEN 512
-#define MAX_NUM_PARTS 16
-
-/* known partition schemes */
-#define PART_SCHEME_MBR 0x1
-#define PART_SCHEME_GPT 0x2
-
-/* PC Bios partition status */
-#define PC_PART_ACTIVE 0x80
-#define PC_PART_NORMAL 0x0
-
-/* Known (rather, used by us) partition types */
-#define PC_PART_TYPE_LINUX 0x83
-#define PC_PART_TYPE_EXTENDED 0x05
-#define PC_PART_TYPE_FAT32 0x0c
-
-#define PC_NUM_BOOT_RECORD_PARTS 4
-
-#define PC_EBR_LOGICAL_PART 0
-#define PC_EBR_NEXT_PTR_PART 1
-
-#define PC_BIOS_BOOT_SIG 0xAA55
-
-#define PC_MBR_DISK_OFFSET 0
-#define PC_MBR_SIZE 512
-
-#define PART_ACTIVE_FLAG 0x1
-
-struct chs {
- uint8_t head;
- uint8_t sector;
- uint8_t cylinder;
-} __attribute__((__packed__));
-
-/* 16 byte pc partition descriptor that sits in MBR and EPBR.
- * Note: multi-byte entities have little-endian layout on disk */
-struct pc_partition {
- uint8_t status; /* byte 0 */
- struct chs start; /* bytes 1-3 */
- uint8_t type; /* byte 4 */
- struct chs end; /* bytes 5-7 */
- uint32_t start_lba; /* bytes 8-11 */
- uint32_t len_lba; /* bytes 12-15 */
-} __attribute__((__packed__));
-
-struct pc_boot_record {
- uint8_t code[440]; /* bytes 0-439 */
- uint32_t disk_sig; /* bytes 440-443 */
- uint16_t pad; /* bytes 444-445 */
- struct pc_partition ptable[PC_NUM_BOOT_RECORD_PARTS]; /* bytes 446-509 */
- uint16_t mbr_sig; /* bytes 510-511 */
-} __attribute__((__packed__));
-
-struct part_info {
- char *name;
- uint8_t flags;
- uint8_t type;
- uint32_t len_kb; /* in 1K-bytes */
- uint32_t start_lba; /* the LBA where this partition begins */
-};
-
-struct disk_info {
- char *device;
- uint8_t scheme;
- int sect_size; /* expected sector size in bytes. MUST BE POWER OF 2 */
- uint32_t skip_lba; /* in sectors (1 unit of LBA) */
- uint32_t num_lba; /* the size of the disk in LBA units */
- struct part_info *part_lst;
- int num_parts;
-};
-
-struct write_list {
- struct write_list *next;
- loff_t offset;
- uint32_t len;
- uint8_t data[0];
-};
-
-
-struct write_list *alloc_wl(uint32_t data_len);
-void free_wl(struct write_list *item);
-struct write_list *wlist_add(struct write_list **lst, struct write_list *item);
-void wlist_free(struct write_list *lst);
-int wlist_commit(int fd, struct write_list *lst, int test);
-
-struct disk_info *load_diskconfig(const char *fn, char *path_override);
-int dump_disk_config(struct disk_info *dinfo);
-int apply_disk_config(struct disk_info *dinfo, int test);
-char *find_part_device(struct disk_info *dinfo, const char *name);
-int process_disk_config(struct disk_info *dinfo);
-struct part_info *find_part(struct disk_info *dinfo, const char *name);
-
-int write_raw_image(const char *dst, const char *src, loff_t offset, int test);
-
-/* For MBR partition schemes */
-struct write_list *config_mbr(struct disk_info *dinfo);
-char *find_mbr_part(struct disk_info *dinfo, const char *name);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LIBS_DISKCONFIG_H */
diff --git a/libdiskconfig/write_lst.c b/libdiskconfig/write_lst.c
deleted file mode 100644
index c3d5c0a..0000000
--- a/libdiskconfig/write_lst.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* libs/diskconfig/write_lst.c
- *
- * Copyright 2008, 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.
- */
-
-#define LOG_TAG "write_lst"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <diskconfig/diskconfig.h>
-#include <log/log.h>
-
-struct write_list *
-alloc_wl(uint32_t data_len)
-{
- struct write_list *item;
-
- if (!(item = malloc(sizeof(struct write_list) + data_len))) {
- ALOGE("Unable to allocate memory.");
- return NULL;
- }
-
- item->len = data_len;
- return item;
-}
-
-void
-free_wl(struct write_list *item)
-{
- if (item)
- free(item);
-}
-
-struct write_list *
-wlist_add(struct write_list **lst, struct write_list *item)
-{
- item->next = (*lst);
- *lst = item;
- return item;
-}
-
-void
-wlist_free(struct write_list *lst)
-{
- struct write_list *temp_wr;
- while (lst) {
- temp_wr = lst->next;
- free_wl(lst);
- lst = temp_wr;
- }
-}
-
-int
-wlist_commit(int fd, struct write_list *lst, int test)
-{
- for(; lst; lst = lst->next) {
- if (lseek64(fd, lst->offset, SEEK_SET) != (loff_t)lst->offset) {
- ALOGE("Cannot seek to the specified position (%lld).", (long long)lst->offset);
- goto fail;
- }
-
- if (!test) {
- if (write(fd, lst->data, lst->len) != (int)lst->len) {
- ALOGE("Failed writing %u bytes at position %lld.", lst->len,
- (long long)lst->offset);
- goto fail;
- }
- } else
- ALOGI("Would write %d bytes @ offset %lld.", lst->len, (long long)lst->offset);
- }
-
- return 0;
-
-fail:
- return -1;
-}
diff --git a/libmodprobe/Android.bp b/libmodprobe/Android.bp
index 525a880..1d94a96 100644
--- a/libmodprobe/Android.bp
+++ b/libmodprobe/Android.bp
@@ -10,6 +10,7 @@
vendor_available: true,
ramdisk_available: true,
recovery_available: true,
+ host_supported: true,
srcs: [
"libmodprobe.cpp",
"libmodprobe_ext.cpp",
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 6c5ca99..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;
@@ -568,7 +569,7 @@
// Attempt to match both the canonical module name and the module filename.
if (!fnmatch(pattern.c_str(), module.c_str(), 0)) {
rv.emplace_back(module);
- } else if (!fnmatch(pattern.c_str(), basename(deps[0].c_str()), 0)) {
+ } else if (!fnmatch(pattern.c_str(), android::base::Basename(deps[0]).c_str(), 0)) {
rv.emplace_back(deps[0]);
}
}
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/libprocessgroup/OWNERS b/libprocessgroup/OWNERS
index 8ebb8cc..d5aa721 100644
--- a/libprocessgroup/OWNERS
+++ b/libprocessgroup/OWNERS
@@ -1,2 +1,4 @@
-ccross@google.com
+# Bug component: 1293033
surenb@google.com
+tjmercier@google.com
+carlosgalo@google.com
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 8c00326..ce7f10b 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -49,7 +49,7 @@
static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs";
static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
-static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.tasks";
+static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.threads";
uint32_t CgroupController::version() const {
CHECK(HasValue());
@@ -229,12 +229,17 @@
auto controller_count = ACgroupFile_getControllerCount();
for (uint32_t i = 0; i < controller_count; ++i) {
const ACgroupController* controller = ACgroupFile_getController(i);
- if (ACgroupController_getFlags(controller) &
- CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) {
+ const uint32_t flags = ACgroupController_getFlags(controller);
+ if (flags & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) {
std::string str("+");
str.append(ACgroupController_getName(controller));
if (!WriteStringToFile(str, path + "/cgroup.subtree_control")) {
- return -errno;
+ if (flags & CGROUPRC_CONTROLLER_FLAG_OPTIONAL) {
+ PLOG(WARNING) << "Activation of cgroup controller " << str
+ << " failed in path " << path;
+ } else {
+ return -errno;
+ }
}
}
}
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 9b2d775..dbaeb93 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -36,6 +36,7 @@
bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache = false);
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
+bool SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles);
__END_DECLS
@@ -75,6 +76,11 @@
// that it only returns 0 in the case that the cgroup exists and it contains no processes.
int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes = nullptr);
+// Sends the provided signal to all members of a process group, but does not wait for processes to
+// exit, or for the cgroup to be removed. Callers should also ensure that killProcessGroup is called
+// later to ensure the cgroup is fully removed, otherwise system resources may leak.
+int sendSignalToProcessGroup(uid_t uid, int initialPid, int signal);
+
int createProcessGroup(uid_t uid, int initialPid, bool memControl = false);
// Set various properties of a process group. For these functions to work, the process group must
@@ -90,6 +96,10 @@
// Returns false in case of error, true in case of success
bool getAttributePathForTask(const std::string& attr_name, int tid, std::string* path);
+// Check if a profile can be applied without failing.
+// Returns true if it can be applied without failing, false otherwise
+bool isProfileValidForProcess(const std::string& profile_name, int uid, int pid);
+
#endif // __ANDROID_VNDK__
__END_DECLS
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 3fac373..1f29040 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -200,6 +200,11 @@
return SetProcessProfiles(uid, pid, std::span<const std::string_view>(profiles_));
}
+bool SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles) {
+ return TaskProfiles::GetInstance().SetUserProfiles(uid, std::span<const std::string>(profiles),
+ false);
+}
+
static std::string ConvertUidToPath(const char* cgroup, uid_t uid) {
return StringPrintf("%s/uid_%d", cgroup, uid);
}
@@ -211,7 +216,6 @@
static int RemoveProcessGroup(const char* cgroup, uid_t uid, int pid, unsigned int retries) {
int ret = 0;
auto uid_pid_path = ConvertUidPidToPath(cgroup, uid, pid);
- auto uid_path = ConvertUidToPath(cgroup, uid);
while (retries--) {
ret = rmdir(uid_pid_path.c_str());
@@ -367,50 +371,57 @@
// Returns 0 if there are no processes in the process cgroup left to kill
// Returns -1 on error
static int DoKillProcessGroupOnce(const char* cgroup, uid_t uid, int initialPid, int signal) {
- auto path = ConvertUidPidToPath(cgroup, uid, initialPid) + PROCESSGROUP_CGROUP_PROCS_FILE;
- std::unique_ptr<FILE, decltype(&fclose)> fd(fopen(path.c_str(), "re"), fclose);
- if (!fd) {
- if (errno == ENOENT) {
- // This happens when process is already dead
- return 0;
- }
- PLOG(WARNING) << __func__ << " failed to open process cgroup uid " << uid << " pid "
- << initialPid;
- return -1;
- }
-
// We separate all of the pids in the cgroup into those pids that are also the leaders of
// process groups (stored in the pgids set) and those that are not (stored in the pids set).
std::set<pid_t> pgids;
pgids.emplace(initialPid);
std::set<pid_t> pids;
-
- pid_t pid;
int processes = 0;
- while (fscanf(fd.get(), "%d\n", &pid) == 1 && pid >= 0) {
- processes++;
- if (pid == 0) {
- // Should never happen... but if it does, trying to kill this
- // will boomerang right back and kill us! Let's not let that happen.
- LOG(WARNING) << "Yikes, we've been told to kill pid 0! How about we don't do that?";
- continue;
- }
- pid_t pgid = getpgid(pid);
- if (pgid == -1) PLOG(ERROR) << "getpgid(" << pid << ") failed";
- if (pgid == pid) {
- pgids.emplace(pid);
- } else {
- pids.emplace(pid);
- }
- }
- // Erase all pids that will be killed when we kill the process groups.
- for (auto it = pids.begin(); it != pids.end();) {
- pid_t pgid = getpgid(*it);
- if (pgids.count(pgid) == 1) {
- it = pids.erase(it);
- } else {
- ++it;
+ std::unique_ptr<FILE, decltype(&fclose)> fd(nullptr, fclose);
+
+ if (CgroupsAvailable()) {
+ auto path = ConvertUidPidToPath(cgroup, uid, initialPid) + PROCESSGROUP_CGROUP_PROCS_FILE;
+ fd.reset(fopen(path.c_str(), "re"));
+ if (!fd) {
+ if (errno == ENOENT) {
+ // This happens when process is already dead
+ return 0;
+ }
+ PLOG(WARNING) << __func__ << " failed to open process cgroup uid " << uid << " pid "
+ << initialPid;
+ return -1;
+ }
+ pid_t pid;
+ bool file_is_empty = true;
+ while (fscanf(fd.get(), "%d\n", &pid) == 1 && pid >= 0) {
+ processes++;
+ file_is_empty = false;
+ if (pid == 0) {
+ // Should never happen... but if it does, trying to kill this
+ // will boomerang right back and kill us! Let's not let that happen.
+ LOG(WARNING)
+ << "Yikes, we've been told to kill pid 0! How about we don't do that?";
+ continue;
+ }
+ pid_t pgid = getpgid(pid);
+ if (pgid == -1) PLOG(ERROR) << "getpgid(" << pid << ") failed";
+ if (pgid == pid) {
+ pgids.emplace(pid);
+ } else {
+ pids.emplace(pid);
+ }
+ }
+ if (!file_is_empty) {
+ // Erase all pids that will be killed when we kill the process groups.
+ for (auto it = pids.begin(); it != pids.end();) {
+ pid_t pgid = getpgid(*it);
+ if (pgids.count(pgid) == 1) {
+ it = pids.erase(it);
+ } else {
+ ++it;
+ }
+ }
}
}
@@ -434,13 +445,18 @@
}
}
- return feof(fd.get()) ? processes : -1;
+ return (!fd || feof(fd.get())) ? processes : -1;
}
static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries,
int* max_processes) {
+ CHECK_GE(uid, 0);
+ CHECK_GT(initialPid, 0);
+
std::string hierarchy_root_path;
- CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &hierarchy_root_path);
+ if (CgroupsAvailable()) {
+ CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &hierarchy_root_path);
+ }
const char* cgroup = hierarchy_root_path.c_str();
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
@@ -456,6 +472,11 @@
*max_processes = processes;
}
LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid;
+ if (!CgroupsAvailable()) {
+ // makes no sense to retry, because there are no cgroup_procs file
+ processes = 0; // no remaining processes
+ break;
+ }
if (retry > 0) {
std::this_thread::sleep_for(5ms);
--retry;
@@ -485,6 +506,11 @@
<< " in " << static_cast<int>(ms) << "ms";
}
+ if (!CgroupsAvailable()) {
+ // nothing to do here, if cgroups isn't available
+ return 0;
+ }
+
// 400 retries correspond to 2 secs max timeout
int err = RemoveProcessGroup(cgroup, uid, initialPid, 400);
@@ -515,6 +541,15 @@
return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/, max_processes);
}
+int sendSignalToProcessGroup(uid_t uid, int initialPid, int signal) {
+ std::string hierarchy_root_path;
+ if (CgroupsAvailable()) {
+ CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &hierarchy_root_path);
+ }
+ const char* cgroup = hierarchy_root_path.c_str();
+ return DoKillProcessGroupOnce(cgroup, uid, initialPid, signal);
+}
+
static int createProcessGroupInternal(uid_t uid, int initialPid, std::string cgroup,
bool activate_controllers) {
auto uid_path = ConvertUidToPath(cgroup.c_str(), uid);
@@ -563,7 +598,8 @@
}
int createProcessGroup(uid_t uid, int initialPid, bool memControl) {
- std::string cgroup;
+ CHECK_GE(uid, 0);
+ CHECK_GT(initialPid, 0);
if (memControl && !UsePerAppMemcg()) {
PLOG(ERROR) << "service memory controls are used without per-process memory cgroup support";
@@ -581,6 +617,7 @@
}
}
+ std::string cgroup;
CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &cgroup);
return createProcessGroupInternal(uid, initialPid, cgroup, true);
}
@@ -619,3 +656,13 @@
bool getAttributePathForTask(const std::string& attr_name, int tid, std::string* path) {
return CgroupGetAttributePathForTask(attr_name, tid, path);
}
+
+bool isProfileValidForProcess(const std::string& profile_name, int uid, int pid) {
+ const TaskProfile* tp = TaskProfiles::GetInstance().GetProfile(profile_name);
+
+ if (tp == nullptr) {
+ return false;
+ }
+
+ return tp->IsValidForProcess(uid, pid);
+}
\ No newline at end of file
diff --git a/libprocessgroup/profiles/cgroups.json b/libprocessgroup/profiles/cgroups.json
index 3e4393d..d013ec8 100644
--- a/libprocessgroup/profiles/cgroups.json
+++ b/libprocessgroup/profiles/cgroups.json
@@ -1,13 +1,6 @@
{
"Cgroups": [
{
- "Controller": "blkio",
- "Path": "/dev/blkio",
- "Mode": "0775",
- "UID": "system",
- "GID": "system"
- },
- {
"Controller": "cpu",
"Path": "/dev/cpuctl",
"Mode": "0755",
@@ -39,6 +32,12 @@
{
"Controller": "freezer",
"Path": "."
+ },
+ {
+ "Controller": "io",
+ "Path": ".",
+ "NeedsActivation": true,
+ "Optional": true
}
]
}
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 15f95fc..12f7b44 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -80,17 +80,20 @@
{
"Name": "BfqWeight",
"Controller": "io",
- "File": "io.bfq.weight"
+ "File": "blkio.bfq.weight",
+ "FileV2": "io.bfq.weight"
},
{
"Name": "CfqGroupIdle",
"Controller": "io",
- "File": "io.group_idle"
+ "File": "blkio.group_idle",
+ "FileV2": "io.group_idle"
},
{
"Name": "CfqWeight",
"Controller": "io",
- "File": "io.weight"
+ "File": "blkio.weight",
+ "FileV2": "io.weight"
}
],
@@ -454,14 +457,6 @@
"Name": "LowIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
- "Params":
- {
- "Controller": "blkio",
- "Path": "background"
- }
- },
- {
"Name": "SetAttribute",
"Params":
{
@@ -494,14 +489,6 @@
"Name": "NormalIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
- "Params":
- {
- "Controller": "blkio",
- "Path": ""
- }
- },
- {
"Name": "SetAttribute",
"Params":
{
@@ -534,14 +521,6 @@
"Name": "HighIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
- "Params":
- {
- "Controller": "blkio",
- "Path": ""
- }
- },
- {
"Name": "SetAttribute",
"Params":
{
@@ -574,14 +553,6 @@
"Name": "MaxIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
- "Params":
- {
- "Controller": "blkio",
- "Path": ""
- }
- },
- {
"Name": "SetAttribute",
"Params":
{
@@ -806,6 +777,10 @@
"Profiles": [ "Dex2oatPerformance", "LowIoPriority", "TimerSlackHigh" ]
},
{
+ "Name": "Dex2OatBackground",
+ "Profiles": [ "Dex2OatBootComplete" ]
+ },
+ {
"Name": "OtaProfiles",
"Profiles": [ "ServiceCapacityLow", "LowIoPriority", "HighEnergySaving" ]
}
diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp
index 304248a..fbeedf9 100644
--- a/libprocessgroup/setup/cgroup_map_write.cpp
+++ b/libprocessgroup/setup/cgroup_map_write.cpp
@@ -254,86 +254,64 @@
// To avoid issues in sdk_mac build
#if defined(__ANDROID__)
-static bool SetupCgroup(const CgroupDescriptor& descriptor) {
+static bool IsOptionalController(const format::CgroupController* controller) {
+ return controller->flags() & CGROUPRC_CONTROLLER_FLAG_OPTIONAL;
+}
+
+static bool MountV2CgroupController(const CgroupDescriptor& descriptor) {
const format::CgroupController* controller = descriptor.controller();
- int result;
- if (controller->version() == 2) {
- result = 0;
- if (!strcmp(controller->name(), CGROUPV2_CONTROLLER_NAME)) {
- // /sys/fs/cgroup is created by cgroup2 with specific selinux permissions,
- // try to create again in case the mount point is changed
- if (!Mkdir(controller->path(), 0, "", "")) {
- LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
- return false;
- }
+ // /sys/fs/cgroup is created by cgroup2 with specific selinux permissions,
+ // try to create again in case the mount point is changed
+ if (!Mkdir(controller->path(), 0, "", "")) {
+ LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
+ return false;
+ }
- // The memory_recursiveprot mount option has been introduced by kernel commit
- // 8a931f801340 ("mm: memcontrol: recursive memory.low protection"; v5.7). Try first to
- // mount with that option enabled. If mounting fails because the kernel is too old,
- // retry without that mount option.
- if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
- "memory_recursiveprot") < 0) {
- LOG(INFO) << "Mounting memcg with memory_recursiveprot failed. Retrying without.";
- if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
- nullptr) < 0) {
- PLOG(ERROR) << "Failed to mount cgroup v2";
- }
- }
-
- // selinux permissions change after mounting, so it's ok to change mode and owner now
- if (!ChangeDirModeAndOwner(controller->path(), descriptor.mode(), descriptor.uid(),
- descriptor.gid())) {
- LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
- result = -1;
- }
- } else {
- if (!Mkdir(controller->path(), descriptor.mode(), descriptor.uid(), descriptor.gid())) {
- LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
- return false;
- }
-
- if (controller->flags() & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) {
- std::string str = std::string("+") + controller->name();
- std::string path = std::string(controller->path()) + "/cgroup.subtree_control";
-
- if (!base::WriteStringToFile(str, path)) {
- LOG(ERROR) << "Failed to activate controller " << controller->name();
- return false;
- }
- }
- }
- } else {
- // mkdir <path> [mode] [owner] [group]
- if (!Mkdir(controller->path(), descriptor.mode(), descriptor.uid(), descriptor.gid())) {
- LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
- return false;
- }
-
- // Unfortunately historically cpuset controller was mounted using a mount command
- // different from all other controllers. This results in controller attributes not
- // to be prepended with controller name. For example this way instead of
- // /dev/cpuset/cpuset.cpus the attribute becomes /dev/cpuset/cpus which is what
- // the system currently expects.
- if (!strcmp(controller->name(), "cpuset")) {
- // mount cpuset none /dev/cpuset nodev noexec nosuid
- result = mount("none", controller->path(), controller->name(),
- MS_NODEV | MS_NOEXEC | MS_NOSUID, nullptr);
- } else {
- // mount cgroup none <path> nodev noexec nosuid <controller>
- result = mount("none", controller->path(), "cgroup", MS_NODEV | MS_NOEXEC | MS_NOSUID,
- controller->name());
+ // The memory_recursiveprot mount option has been introduced by kernel commit
+ // 8a931f801340 ("mm: memcontrol: recursive memory.low protection"; v5.7). Try first to
+ // mount with that option enabled. If mounting fails because the kernel is too old,
+ // retry without that mount option.
+ if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+ "memory_recursiveprot") < 0) {
+ LOG(INFO) << "Mounting memcg with memory_recursiveprot failed. Retrying without.";
+ if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+ nullptr) < 0) {
+ PLOG(ERROR) << "Failed to mount cgroup v2";
+ return IsOptionalController(controller);
}
}
- if (result < 0) {
- bool optional = controller->flags() & CGROUPRC_CONTROLLER_FLAG_OPTIONAL;
+ // selinux permissions change after mounting, so it's ok to change mode and owner now
+ if (!ChangeDirModeAndOwner(controller->path(), descriptor.mode(), descriptor.uid(),
+ descriptor.gid())) {
+ PLOG(ERROR) << "Change of ownership or mode failed for controller " << controller->name();
+ return IsOptionalController(controller);
+ }
- if (optional && errno == EINVAL) {
- // Optional controllers are allowed to fail to mount if kernel does not support them
- LOG(INFO) << "Optional " << controller->name() << " cgroup controller is not mounted";
- } else {
- PLOG(ERROR) << "Failed to mount " << controller->name() << " cgroup";
+ return true;
+}
+
+static bool ActivateV2CgroupController(const CgroupDescriptor& descriptor) {
+ const format::CgroupController* controller = descriptor.controller();
+
+ if (!Mkdir(controller->path(), descriptor.mode(), descriptor.uid(), descriptor.gid())) {
+ LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
+ return false;
+ }
+
+ if (controller->flags() & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) {
+ std::string str = "+";
+ str += controller->name();
+ std::string path = controller->path();
+ path += "/cgroup.subtree_control";
+
+ if (!base::WriteStringToFile(str, path)) {
+ if (IsOptionalController(controller)) {
+ PLOG(INFO) << "Failed to activate optional controller " << controller->name();
+ return true;
+ }
+ PLOG(ERROR) << "Failed to activate controller " << controller->name();
return false;
}
}
@@ -341,6 +319,55 @@
return true;
}
+static bool MountV1CgroupController(const CgroupDescriptor& descriptor) {
+ const format::CgroupController* controller = descriptor.controller();
+
+ // mkdir <path> [mode] [owner] [group]
+ if (!Mkdir(controller->path(), descriptor.mode(), descriptor.uid(), descriptor.gid())) {
+ LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
+ return false;
+ }
+
+ // Unfortunately historically cpuset controller was mounted using a mount command
+ // different from all other controllers. This results in controller attributes not
+ // to be prepended with controller name. For example this way instead of
+ // /dev/cpuset/cpuset.cpus the attribute becomes /dev/cpuset/cpus which is what
+ // the system currently expects.
+ int res;
+ if (!strcmp(controller->name(), "cpuset")) {
+ // mount cpuset none /dev/cpuset nodev noexec nosuid
+ res = mount("none", controller->path(), controller->name(),
+ MS_NODEV | MS_NOEXEC | MS_NOSUID, nullptr);
+ } else {
+ // mount cgroup none <path> nodev noexec nosuid <controller>
+ res = mount("none", controller->path(), "cgroup", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+ controller->name());
+ }
+ if (res != 0) {
+ if (IsOptionalController(controller)) {
+ PLOG(INFO) << "Failed to mount optional controller " << controller->name();
+ return true;
+ }
+ PLOG(ERROR) << "Failed to mount controller " << controller->name();
+ return false;
+ }
+ return true;
+}
+
+static bool SetupCgroup(const CgroupDescriptor& descriptor) {
+ const format::CgroupController* controller = descriptor.controller();
+
+ if (controller->version() == 2) {
+ if (!strcmp(controller->name(), CGROUPV2_CONTROLLER_NAME)) {
+ return MountV2CgroupController(descriptor);
+ } else {
+ return ActivateV2CgroupController(descriptor);
+ }
+ } else {
+ return MountV1CgroupController(descriptor);
+ }
+}
+
#else
// Stubs for non-Android targets.
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 35adf36..44dba2a 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -139,6 +139,17 @@
return true;
}
+bool ProfileAttribute::GetPathForUID(uid_t uid, std::string* path) const {
+ if (path == nullptr) {
+ return true;
+ }
+
+ const std::string& file_name =
+ controller()->version() == 2 && !file_v2_name_.empty() ? file_v2_name_ : file_name_;
+ *path = StringPrintf("%s/uid_%d/%s", controller()->path(), uid, file_name.c_str());
+ return true;
+}
+
bool SetClampsAction::ExecuteForProcess(uid_t, pid_t) const {
// TODO: add support when kernel supports util_clamp
LOG(WARNING) << "SetClampsAction::ExecuteForProcess is not supported";
@@ -225,6 +236,54 @@
return true;
}
+bool SetAttributeAction::ExecuteForUID(uid_t uid) const {
+ std::string path;
+
+ if (!attribute_->GetPathForUID(uid, &path)) {
+ LOG(ERROR) << "Failed to find cgroup for uid " << uid;
+ return false;
+ }
+
+ if (!WriteStringToFile(value_, path)) {
+ if (access(path.c_str(), F_OK) < 0) {
+ if (optional_) {
+ return true;
+ } else {
+ LOG(ERROR) << "No such cgroup attribute: " << path;
+ return false;
+ }
+ }
+ PLOG(ERROR) << "Failed to write '" << value_ << "' to " << path;
+ return false;
+ }
+ return true;
+}
+
+bool SetAttributeAction::IsValidForProcess(uid_t, pid_t pid) const {
+ return IsValidForTask(pid);
+}
+
+bool SetAttributeAction::IsValidForTask(int tid) const {
+ std::string path;
+
+ if (!attribute_->GetPathForTask(tid, &path)) {
+ return false;
+ }
+
+ if (!access(path.c_str(), W_OK)) {
+ // operation will succeed
+ return true;
+ }
+
+ if (!access(path.c_str(), F_OK)) {
+ // file exists but not writable
+ return false;
+ }
+
+ // file does not exist, ignore if optional
+ return optional_;
+}
+
SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p)
: controller_(c), path_(p) {
FdCacheHelper::Init(controller_.GetTasksFilePath(path_), fd_[ProfileAction::RCT_TASK]);
@@ -362,6 +421,39 @@
FdCacheHelper::Drop(fd_[cache_type]);
}
+bool SetCgroupAction::IsValidForProcess(uid_t uid, pid_t pid) const {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
+ if (FdCacheHelper::IsCached(fd_[ProfileAction::RCT_PROCESS])) {
+ return true;
+ }
+
+ if (fd_[ProfileAction::RCT_PROCESS] == FdCacheHelper::FDS_INACCESSIBLE) {
+ return false;
+ }
+
+ std::string procs_path = controller()->GetProcsFilePath(path_, uid, pid);
+ return access(procs_path.c_str(), W_OK) == 0;
+}
+
+bool SetCgroupAction::IsValidForTask(int) const {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
+ if (FdCacheHelper::IsCached(fd_[ProfileAction::RCT_TASK])) {
+ return true;
+ }
+
+ if (fd_[ProfileAction::RCT_TASK] == FdCacheHelper::FDS_INACCESSIBLE) {
+ return false;
+ }
+
+ if (fd_[ProfileAction::RCT_TASK] == FdCacheHelper::FDS_APP_DEPENDENT) {
+ // application-dependent path can't be used with tid
+ return false;
+ }
+
+ std::string tasks_path = controller()->GetTasksFilePath(path_);
+ return access(tasks_path.c_str(), W_OK) == 0;
+}
+
WriteFileAction::WriteFileAction(const std::string& task_path, const std::string& proc_path,
const std::string& value, bool logfailures)
: task_path_(task_path), proc_path_(proc_path), value_(value), logfailures_(logfailures) {
@@ -498,6 +590,37 @@
FdCacheHelper::Drop(fd_[cache_type]);
}
+bool WriteFileAction::IsValidForProcess(uid_t, pid_t) const {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
+ if (FdCacheHelper::IsCached(fd_[ProfileAction::RCT_PROCESS])) {
+ return true;
+ }
+
+ if (fd_[ProfileAction::RCT_PROCESS] == FdCacheHelper::FDS_INACCESSIBLE) {
+ return false;
+ }
+
+ return access(proc_path_.empty() ? task_path_.c_str() : proc_path_.c_str(), W_OK) == 0;
+}
+
+bool WriteFileAction::IsValidForTask(int) const {
+ std::lock_guard<std::mutex> lock(fd_mutex_);
+ if (FdCacheHelper::IsCached(fd_[ProfileAction::RCT_TASK])) {
+ return true;
+ }
+
+ if (fd_[ProfileAction::RCT_TASK] == FdCacheHelper::FDS_INACCESSIBLE) {
+ return false;
+ }
+
+ if (fd_[ProfileAction::RCT_TASK] == FdCacheHelper::FDS_APP_DEPENDENT) {
+ // application-dependent path can't be used with tid
+ return false;
+ }
+
+ return access(task_path_.c_str(), W_OK) == 0;
+}
+
bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
for (const auto& profile : profiles_) {
profile->ExecuteForProcess(uid, pid);
@@ -524,6 +647,24 @@
}
}
+bool ApplyProfileAction::IsValidForProcess(uid_t uid, pid_t pid) const {
+ for (const auto& profile : profiles_) {
+ if (!profile->IsValidForProcess(uid, pid)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ApplyProfileAction::IsValidForTask(int tid) const {
+ for (const auto& profile : profiles_) {
+ if (!profile->IsValidForTask(tid)) {
+ return false;
+ }
+ }
+ return true;
+}
+
void TaskProfile::MoveTo(TaskProfile* profile) {
profile->elements_ = std::move(elements_);
profile->res_cached_ = res_cached_;
@@ -552,6 +693,16 @@
return true;
}
+bool TaskProfile::ExecuteForUID(uid_t uid) const {
+ for (const auto& element : elements_) {
+ if (!element->ExecuteForUID(uid)) {
+ LOG(VERBOSE) << "Applying profile action " << element->Name() << " failed";
+ return false;
+ }
+ }
+ return true;
+}
+
void TaskProfile::EnableResourceCaching(ProfileAction::ResourceCacheType cache_type) {
if (res_cached_) {
return;
@@ -576,6 +727,20 @@
res_cached_ = false;
}
+bool TaskProfile::IsValidForProcess(uid_t uid, pid_t pid) const {
+ for (const auto& element : elements_) {
+ if (!element->IsValidForProcess(uid, pid)) return false;
+ }
+ return true;
+}
+
+bool TaskProfile::IsValidForTask(int tid) const {
+ for (const auto& element : elements_) {
+ if (!element->IsValidForTask(tid)) return false;
+ }
+ return true;
+}
+
void TaskProfiles::DropResourceCaching(ProfileAction::ResourceCacheType cache_type) const {
for (auto& iter : profiles_) {
iter.second->DropResourceCaching(cache_type);
@@ -805,6 +970,24 @@
}
template <typename T>
+bool TaskProfiles::SetUserProfiles(uid_t uid, std::span<const T> profiles, bool use_fd_cache) {
+ for (const auto& name : profiles) {
+ TaskProfile* profile = GetProfile(name);
+ if (profile != nullptr) {
+ if (use_fd_cache) {
+ profile->EnableResourceCaching(ProfileAction::RCT_PROCESS);
+ }
+ if (!profile->ExecuteForUID(uid)) {
+ PLOG(WARNING) << "Failed to apply " << name << " process profile";
+ }
+ } else {
+ PLOG(WARNING) << "Failed to find " << name << "process profile";
+ }
+ }
+ return true;
+}
+
+template <typename T>
bool TaskProfiles::SetProcessProfiles(uid_t uid, pid_t pid, std::span<const T> profiles,
bool use_fd_cache) {
bool success = true;
@@ -815,11 +998,11 @@
profile->EnableResourceCaching(ProfileAction::RCT_PROCESS);
}
if (!profile->ExecuteForProcess(uid, pid)) {
- PLOG(WARNING) << "Failed to apply " << name << " process profile";
+ LOG(WARNING) << "Failed to apply " << name << " process profile";
success = false;
}
} else {
- PLOG(WARNING) << "Failed to find " << name << " process profile";
+ LOG(WARNING) << "Failed to find " << name << " process profile";
success = false;
}
}
@@ -836,11 +1019,11 @@
profile->EnableResourceCaching(ProfileAction::RCT_TASK);
}
if (!profile->ExecuteForTask(tid)) {
- PLOG(WARNING) << "Failed to apply " << name << " task profile";
+ LOG(WARNING) << "Failed to apply " << name << " task profile";
success = false;
}
} else {
- PLOG(WARNING) << "Failed to find " << name << " task profile";
+ LOG(WARNING) << "Failed to find " << name << " task profile";
success = false;
}
}
@@ -857,3 +1040,5 @@
bool use_fd_cache);
template bool TaskProfiles::SetTaskProfiles(int tid, std::span<const std::string_view> profiles,
bool use_fd_cache);
+template bool TaskProfiles::SetUserProfiles(uid_t uid, std::span<const std::string> profiles,
+ bool use_fd_cache);
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 85b3f91..a62c5b0 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -36,6 +36,7 @@
virtual const CgroupController* controller() const = 0;
virtual const std::string& file_name() const = 0;
virtual bool GetPathForTask(int tid, std::string* path) const = 0;
+ virtual bool GetPathForUID(uid_t uid, std::string* path) const = 0;
};
class ProfileAttribute : public IProfileAttribute {
@@ -53,6 +54,7 @@
void Reset(const CgroupController& controller, const std::string& file_name) override;
bool GetPathForTask(int tid, std::string* path) const override;
+ bool GetPathForUID(uid_t uid, std::string* path) const override;
private:
CgroupController controller_;
@@ -70,11 +72,14 @@
virtual const char* Name() const = 0;
// Default implementations will fail
- virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; };
- virtual bool ExecuteForTask(int) const { return false; };
+ virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; }
+ virtual bool ExecuteForTask(int) const { return false; }
+ virtual bool ExecuteForUID(uid_t) const { return false; }
virtual void EnableResourceCaching(ResourceCacheType) {}
virtual void DropResourceCaching(ResourceCacheType) {}
+ virtual bool IsValidForProcess(uid_t uid, pid_t pid) const { return false; }
+ virtual bool IsValidForTask(int tid) const { return false; }
protected:
enum CacheUseResult { SUCCESS, FAIL, UNUSED };
@@ -100,6 +105,8 @@
const char* Name() const override { return "SetTimerSlack"; }
bool ExecuteForTask(int tid) const override;
+ bool IsValidForProcess(uid_t uid, pid_t pid) const override { return true; }
+ bool IsValidForTask(int tid) const override { return true; }
private:
unsigned long slack_;
@@ -116,6 +123,9 @@
const char* Name() const override { return "SetAttribute"; }
bool ExecuteForProcess(uid_t uid, pid_t pid) const override;
bool ExecuteForTask(int tid) const override;
+ bool ExecuteForUID(uid_t uid) const override;
+ bool IsValidForProcess(uid_t uid, pid_t pid) const override;
+ bool IsValidForTask(int tid) const override;
private:
const IProfileAttribute* attribute_;
@@ -133,6 +143,8 @@
bool ExecuteForTask(int tid) const override;
void EnableResourceCaching(ResourceCacheType cache_type) override;
void DropResourceCaching(ResourceCacheType cache_type) override;
+ bool IsValidForProcess(uid_t uid, pid_t pid) const override;
+ bool IsValidForTask(int tid) const override;
const CgroupController* controller() const { return &controller_; }
@@ -157,6 +169,8 @@
bool ExecuteForTask(int tid) const override;
void EnableResourceCaching(ResourceCacheType cache_type) override;
void DropResourceCaching(ResourceCacheType cache_type) override;
+ bool IsValidForProcess(uid_t uid, pid_t pid) const override;
+ bool IsValidForTask(int tid) const override;
private:
std::string task_path_, proc_path_, value_;
@@ -179,8 +193,11 @@
bool ExecuteForProcess(uid_t uid, pid_t pid) const;
bool ExecuteForTask(int tid) const;
+ bool ExecuteForUID(uid_t uid) const;
void EnableResourceCaching(ProfileAction::ResourceCacheType cache_type);
void DropResourceCaching(ProfileAction::ResourceCacheType cache_type);
+ bool IsValidForProcess(uid_t uid, pid_t pid) const;
+ bool IsValidForTask(int tid) const;
private:
const std::string name_;
@@ -199,6 +216,8 @@
bool ExecuteForTask(int tid) const override;
void EnableResourceCaching(ProfileAction::ResourceCacheType cache_type) override;
void DropResourceCaching(ProfileAction::ResourceCacheType cache_type) override;
+ bool IsValidForProcess(uid_t uid, pid_t pid) const override;
+ bool IsValidForTask(int tid) const override;
private:
std::vector<std::shared_ptr<TaskProfile>> profiles_;
@@ -216,6 +235,8 @@
bool SetProcessProfiles(uid_t uid, pid_t pid, std::span<const T> profiles, bool use_fd_cache);
template <typename T>
bool SetTaskProfiles(int tid, std::span<const T> profiles, bool use_fd_cache);
+ template <typename T>
+ bool SetUserProfiles(uid_t uid, std::span<const T> profiles, bool use_fd_cache);
private:
TaskProfiles();
diff --git a/libprocessgroup/task_profiles_test.cpp b/libprocessgroup/task_profiles_test.cpp
index 09ac44c..eadbe76 100644
--- a/libprocessgroup/task_profiles_test.cpp
+++ b/libprocessgroup/task_profiles_test.cpp
@@ -16,6 +16,7 @@
#include "task_profiles.h"
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <gtest/gtest.h>
#include <mntent.h>
#include <processgroup/processgroup.h>
@@ -29,13 +30,14 @@
using ::android::base::LogId;
using ::android::base::LogSeverity;
using ::android::base::SetLogger;
+using ::android::base::Split;
using ::android::base::VERBOSE;
using ::testing::TestWithParam;
using ::testing::Values;
namespace {
-bool IsCgroupV2Mounted() {
+bool IsCgroupV2MountedRw() {
std::unique_ptr<FILE, int (*)(FILE*)> mnts(setmntent("/proc/mounts", "re"), endmntent);
if (!mnts) {
LOG(ERROR) << "Failed to open /proc/mounts";
@@ -43,9 +45,11 @@
}
struct mntent* mnt;
while ((mnt = getmntent(mnts.get()))) {
- if (strcmp(mnt->mnt_fsname, "cgroup2") == 0) {
- return true;
+ if (strcmp(mnt->mnt_type, "cgroup2") != 0) {
+ continue;
}
+ const std::vector<std::string> options = Split(mnt->mnt_opts, ",");
+ return std::count(options.begin(), options.end(), "ro") == 0;
}
return false;
}
@@ -121,6 +125,10 @@
return true;
};
+ bool GetPathForUID(uid_t, std::string*) const override {
+ return false;
+ }
+
private:
const std::string file_name_;
};
@@ -141,8 +149,9 @@
};
TEST_P(SetAttributeFixture, SetAttribute) {
- // Treehugger runs host tests inside a container without cgroupv2 support.
- if (!IsCgroupV2Mounted()) {
+ // Treehugger runs host tests inside a container either without cgroupv2
+ // support or with the cgroup filesystem mounted read-only.
+ if (!IsCgroupV2MountedRw()) {
GTEST_SKIP();
return;
}
@@ -166,6 +175,32 @@
}
}
+class TaskProfileFixture : public TestWithParam<TestParam> {
+ public:
+ ~TaskProfileFixture() = default;
+};
+
+TEST_P(TaskProfileFixture, TaskProfile) {
+ // Treehugger runs host tests inside a container without cgroupv2 support.
+ if (!IsCgroupV2MountedRw()) {
+ GTEST_SKIP();
+ return;
+ }
+ const TestParam params = GetParam();
+ ProfileAttributeMock pa(params.attr_name);
+ // Test simple profile with one action
+ std::shared_ptr<TaskProfile> tp = std::make_shared<TaskProfile>("test_profile");
+ tp->Add(std::make_unique<SetAttributeAction>(&pa, params.attr_value, params.optional_attr));
+ EXPECT_EQ(tp->IsValidForProcess(getuid(), getpid()), params.result);
+ EXPECT_EQ(tp->IsValidForTask(getpid()), params.result);
+ // Test aggregate profile
+ TaskProfile tp2("meta_profile");
+ std::vector<std::shared_ptr<TaskProfile>> profiles = {tp};
+ tp2.Add(std::make_unique<ApplyProfileAction>(profiles));
+ EXPECT_EQ(tp2.IsValidForProcess(getuid(), getpid()), params.result);
+ EXPECT_EQ(tp2.IsValidForTask(getpid()), params.result);
+}
+
// Test the four combinations of optional_attr {false, true} and cgroup attribute { does not exist,
// exists }.
INSTANTIATE_TEST_SUITE_P(
@@ -206,4 +241,28 @@
.log_prefix = "Failed to write",
.log_suffix = geteuid() == 0 ? "Invalid argument" : "Permission denied"}));
+// Test TaskProfile IsValid calls.
+INSTANTIATE_TEST_SUITE_P(
+ TaskProfileTestSuite, TaskProfileFixture,
+ Values(
+ // Test operating on non-existing cgroup attribute fails.
+ TestParam{.attr_name = "no-such-attribute",
+ .attr_value = ".",
+ .optional_attr = false,
+ .result = false},
+ // Test operating on optional non-existing cgroup attribute succeeds.
+ TestParam{.attr_name = "no-such-attribute",
+ .attr_value = ".",
+ .optional_attr = true,
+ .result = true},
+ // Test operating on existing cgroup attribute succeeds.
+ TestParam{.attr_name = "cgroup.procs",
+ .attr_value = ".",
+ .optional_attr = false,
+ .result = true},
+ // Test operating on optional existing cgroup attribute succeeds.
+ TestParam{.attr_name = "cgroup.procs",
+ .attr_value = ".",
+ .optional_attr = true,
+ .result = true}));
} // namespace
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 8e83e16..5a7d0fc 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -28,6 +28,9 @@
"libbase",
],
target: {
+ darwin: {
+ enabled: true,
+ },
windows: {
enabled: true,
},
@@ -52,6 +55,11 @@
],
cflags: ["-Werror"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
cc_binary {
diff --git a/libsparse/backed_block.cpp b/libsparse/backed_block.cpp
index 6229e7c..a0d1cde 100644
--- a/libsparse/backed_block.cpp
+++ b/libsparse/backed_block.cpp
@@ -315,6 +315,10 @@
bb->len = len;
bb->type = BACKED_BLOCK_FILE;
bb->file.filename = strdup(filename);
+ if (!bb->file.filename) {
+ free(bb);
+ return -ENOMEM;
+ }
bb->file.offset = offset;
bb->next = nullptr;
@@ -359,14 +363,17 @@
new_bb->len = bb->len - max_len;
new_bb->block = bb->block + max_len / bbl->block_size;
new_bb->next = bb->next;
- bb->next = new_bb;
- bb->len = max_len;
switch (bb->type) {
case BACKED_BLOCK_DATA:
new_bb->data.data = (char*)bb->data.data + max_len;
break;
case BACKED_BLOCK_FILE:
+ new_bb->file.filename = strdup(bb->file.filename);
+ if (!new_bb->file.filename) {
+ free(new_bb);
+ return -ENOMEM;
+ }
new_bb->file.offset += max_len;
break;
case BACKED_BLOCK_FD:
@@ -376,5 +383,7 @@
break;
}
+ bb->next = new_bb;
+ bb->len = max_len;
return 0;
}
diff --git a/libsparse/output_file.cpp b/libsparse/output_file.cpp
index cb5d730..08312e4 100644
--- a/libsparse/output_file.cpp
+++ b/libsparse/output_file.cpp
@@ -58,6 +58,8 @@
#define container_of(inner, outer_t, elem) ((outer_t*)((char*)(inner)-offsetof(outer_t, elem)))
+static constexpr size_t kMaxMmapSize = 256 * 1024 * 1024;
+
struct output_file_ops {
int (*open)(struct output_file*, int fd);
int (*skip)(struct output_file*, int64_t);
@@ -71,6 +73,7 @@
int (*write_fill_chunk)(struct output_file* out, uint64_t len, uint32_t fill_val);
int (*write_skip_chunk)(struct output_file* out, uint64_t len);
int (*write_end_chunk)(struct output_file* out);
+ int (*write_fd_chunk)(struct output_file* out, uint64_t len, int fd, int64_t offset);
};
struct output_file {
@@ -318,6 +321,26 @@
return 0;
}
+template <typename T>
+static bool write_fd_chunk_range(int fd, int64_t offset, uint64_t len, T callback) {
+ uint64_t bytes_written = 0;
+ int64_t current_offset = offset;
+ while (bytes_written < len) {
+ size_t mmap_size = std::min(static_cast<uint64_t>(kMaxMmapSize), len - bytes_written);
+ auto m = android::base::MappedFile::FromFd(fd, current_offset, mmap_size, PROT_READ);
+ if (!m) {
+ error("failed to mmap region of length %zu", mmap_size);
+ return false;
+ }
+ if (!callback(m->data(), mmap_size)) {
+ return false;
+ }
+ bytes_written += mmap_size;
+ current_offset += mmap_size;
+ }
+ return true;
+}
+
static int write_sparse_skip_chunk(struct output_file* out, uint64_t skip_len) {
chunk_header_t chunk_header;
int ret;
@@ -424,6 +447,61 @@
return 0;
}
+static int write_sparse_fd_chunk(struct output_file* out, uint64_t len, int fd, int64_t offset) {
+ chunk_header_t chunk_header;
+ uint64_t rnd_up_len, zero_len;
+ int ret;
+
+ /* Round up the data length to a multiple of the block size */
+ rnd_up_len = ALIGN(len, out->block_size);
+ zero_len = rnd_up_len - len;
+
+ /* Finally we can safely emit a chunk of data */
+ chunk_header.chunk_type = CHUNK_TYPE_RAW;
+ chunk_header.reserved1 = 0;
+ chunk_header.chunk_sz = rnd_up_len / out->block_size;
+ chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len;
+ ret = out->ops->write(out, &chunk_header, sizeof(chunk_header));
+
+ if (ret < 0) return -1;
+ bool ok = write_fd_chunk_range(fd, offset, len, [&ret, out](char* data, size_t size) -> bool {
+ ret = out->ops->write(out, data, size);
+ if (ret < 0) return false;
+ if (out->use_crc) {
+ out->crc32 = sparse_crc32(out->crc32, data, size);
+ }
+ return true;
+ });
+ if (!ok) return -1;
+ if (zero_len) {
+ uint64_t len = zero_len;
+ uint64_t write_len;
+ while (len) {
+ write_len = std::min(len, (uint64_t)FILL_ZERO_BUFSIZE);
+ ret = out->ops->write(out, out->zero_buf, write_len);
+ if (ret < 0) {
+ return ret;
+ }
+ len -= write_len;
+ }
+
+ if (out->use_crc) {
+ uint64_t len = zero_len;
+ uint64_t write_len;
+ while (len) {
+ write_len = std::min(len, (uint64_t)FILL_ZERO_BUFSIZE);
+ out->crc32 = sparse_crc32(out->crc32, out->zero_buf, write_len);
+ len -= write_len;
+ }
+ }
+ }
+
+ out->cur_out_ptr += rnd_up_len;
+ out->chunk_cnt++;
+
+ return 0;
+}
+
int write_sparse_end_chunk(struct output_file* out) {
chunk_header_t chunk_header;
int ret;
@@ -454,6 +532,7 @@
.write_fill_chunk = write_sparse_fill_chunk,
.write_skip_chunk = write_sparse_skip_chunk,
.write_end_chunk = write_sparse_end_chunk,
+ .write_fd_chunk = write_sparse_fd_chunk,
};
static int write_normal_data_chunk(struct output_file* out, uint64_t len, void* data) {
@@ -495,6 +574,23 @@
return 0;
}
+static int write_normal_fd_chunk(struct output_file* out, uint64_t len, int fd, int64_t offset) {
+ int ret;
+ uint64_t rnd_up_len = ALIGN(len, out->block_size);
+
+ bool ok = write_fd_chunk_range(fd, offset, len, [&ret, out](char* data, size_t size) -> bool {
+ ret = out->ops->write(out, data, size);
+ return ret >= 0;
+ });
+ if (!ok) return ret;
+
+ if (rnd_up_len > len) {
+ ret = out->ops->skip(out, rnd_up_len - len);
+ }
+
+ return ret;
+}
+
static int write_normal_skip_chunk(struct output_file* out, uint64_t len) {
return out->ops->skip(out, len);
}
@@ -508,6 +604,7 @@
.write_fill_chunk = write_normal_fill_chunk,
.write_skip_chunk = write_normal_skip_chunk,
.write_end_chunk = write_normal_end_chunk,
+ .write_fd_chunk = write_normal_fd_chunk,
};
void output_file_close(struct output_file* out) {
@@ -670,10 +767,7 @@
}
int write_fd_chunk(struct output_file* out, uint64_t len, int fd, int64_t offset) {
- auto m = android::base::MappedFile::FromFd(fd, offset, len, PROT_READ);
- if (!m) return -errno;
-
- return out->sparse_ops->write_data_chunk(out, m->size(), m->data());
+ return out->sparse_ops->write_fd_chunk(out, len, fd, offset);
}
/* Write a contiguous region of data blocks from a file */
diff --git a/libsparse/sparse.cpp b/libsparse/sparse.cpp
index 396e7eb..ca7e5fe 100644
--- a/libsparse/sparse.cpp
+++ b/libsparse/sparse.cpp
@@ -260,8 +260,8 @@
return s->block_size;
}
-static struct backed_block* move_chunks_up_to_len(struct sparse_file* from, struct sparse_file* to,
- unsigned int len) {
+static int move_chunks_up_to_len(struct sparse_file* from, struct sparse_file* to, unsigned int len,
+ backed_block** out_bb) {
int64_t count = 0;
struct output_file* out_counter;
struct backed_block* last_bb = nullptr;
@@ -282,7 +282,7 @@
out_counter = output_file_open_callback(out_counter_write, &count, to->block_size, to->len, false,
true, 0, false);
if (!out_counter) {
- return nullptr;
+ return -1;
}
for (bb = start; bb; bb = backed_block_iter_next(bb)) {
@@ -319,7 +319,8 @@
out:
output_file_close(out_counter);
- return bb;
+ *out_bb = bb;
+ return 0;
}
int sparse_file_resparse(struct sparse_file* in_s, unsigned int max_len, struct sparse_file** out_s,
@@ -337,7 +338,15 @@
do {
s = sparse_file_new(in_s->block_size, in_s->len);
- bb = move_chunks_up_to_len(in_s, s, max_len);
+ if (move_chunks_up_to_len(in_s, s, max_len, &bb) < 0) {
+ sparse_file_destroy(s);
+ for (int i = 0; i < c && i < out_s_count; i++) {
+ sparse_file_destroy(out_s[i]);
+ out_s[i] = nullptr;
+ }
+ sparse_file_destroy(tmp);
+ return -1;
+ }
if (c < out_s_count) {
out_s[c] = s;
diff --git a/libstats/expresslog/.clang-format b/libstats/expresslog/.clang-format
new file mode 100644
index 0000000..cead3a0
--- /dev/null
+++ b/libstats/expresslog/.clang-format
@@ -0,0 +1,17 @@
+BasedOnStyle: Google
+AllowShortIfStatementsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: false
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+AccessModifierOffset: -4
+IncludeCategories:
+ - Regex: '^"Log\.h"'
+ Priority: -1
diff --git a/libstats/expresslog/Android.bp b/libstats/expresslog/Android.bp
new file mode 100644
index 0000000..004f8b9
--- /dev/null
+++ b/libstats/expresslog/Android.bp
@@ -0,0 +1,113 @@
+
+//
+// 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.
+//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_defaults {
+ name: "expresslog_defaults",
+ srcs: [
+ "Counter.cpp",
+ "Histogram.cpp",
+ ],
+}
+
+cc_library {
+ name: "libexpresslog",
+ defaults: ["expresslog_defaults"],
+ cflags: [
+ "-DNAMESPACE_FOR_HASH_FUNCTIONS=farmhash",
+ "-Wall",
+ "-Werror",
+ ],
+ header_libs: [
+ "libtextclassifier_hash_headers",
+ ],
+ static_libs: [
+ "libstatslog_express",
+ "libtextclassifier_hash_static",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libstatssocket",
+ ],
+ export_include_dirs: ["include"],
+}
+
+genrule {
+ name: "statslog_express.h",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_express.h --module expresslog --namespace android,expresslog",
+ out: [
+ "statslog_express.h",
+ ],
+}
+
+genrule {
+ name: "statslog_express.cpp",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_express.cpp --module expresslog --namespace android,expresslog --importHeader statslog_express.h",
+ out: [
+ "statslog_express.cpp",
+ ],
+}
+
+cc_library_static {
+ name: "libstatslog_express",
+ generated_sources: ["statslog_express.cpp"],
+ generated_headers: ["statslog_express.h"],
+ export_generated_headers: ["statslog_express.h"],
+ shared_libs: [
+ "libstatssocket",
+ ],
+}
+
+cc_test {
+ name: "expresslog_test",
+ defaults: ["expresslog_defaults"],
+ test_suites: [
+ "general-tests",
+ ],
+ srcs: [
+ "tests/Histogram_test.cpp",
+ ],
+ local_include_dirs: [
+ "include",
+ ],
+ cflags: [
+ "-DNAMESPACE_FOR_HASH_FUNCTIONS=farmhash",
+ "-Wall",
+ "-Wextra",
+ "-Wunused",
+ "-Wpedantic",
+ "-Werror",
+ ],
+ header_libs: [
+ "libtextclassifier_hash_headers",
+ ],
+ static_libs: [
+ "libgmock",
+ "libbase",
+ "liblog",
+ "libstatslog_express",
+ "libtextclassifier_hash_static",
+ ],
+ shared_libs: [
+ "libstatssocket",
+ ]
+}
diff --git a/libstats/expresslog/Counter.cpp b/libstats/expresslog/Counter.cpp
new file mode 100644
index 0000000..9382041
--- /dev/null
+++ b/libstats/expresslog/Counter.cpp
@@ -0,0 +1,37 @@
+//
+// 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 "include/Counter.h"
+
+#include <statslog_express.h>
+#include <string.h>
+#include <utils/hash/farmhash.h>
+
+namespace android {
+namespace expresslog {
+
+void Counter::logIncrement(const char* metricName, int64_t amount) {
+ const int64_t metricIdHash = farmhash::Fingerprint64(metricName, strlen(metricName));
+ stats_write(EXPRESS_EVENT_REPORTED, metricIdHash, amount);
+}
+
+void Counter::logIncrementWithUid(const char* metricName, int32_t uid, int64_t amount) {
+ const int64_t metricIdHash = farmhash::Fingerprint64(metricName, strlen(metricName));
+ stats_write(EXPRESS_UID_EVENT_REPORTED, metricIdHash, amount, uid);
+}
+
+} // namespace expresslog
+} // namespace android
diff --git a/libstats/expresslog/Histogram.cpp b/libstats/expresslog/Histogram.cpp
new file mode 100644
index 0000000..50bb343
--- /dev/null
+++ b/libstats/expresslog/Histogram.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 "include/Histogram.h"
+
+#define LOG_TAG "tex"
+
+#include <log/log.h>
+#include <statslog_express.h>
+#include <string.h>
+#include <utils/hash/farmhash.h>
+
+namespace android {
+namespace expresslog {
+
+std::shared_ptr<Histogram::UniformOptions> Histogram::UniformOptions::create(
+ int binCount, float minValue, float exclusiveMaxValue) {
+ if (binCount < 1) {
+ ALOGE("Bin count should be positive number");
+ return nullptr;
+ }
+
+ if (exclusiveMaxValue <= minValue) {
+ ALOGE("Bins range invalid (maxValue < minValue)");
+ return nullptr;
+ }
+
+ return std::shared_ptr<UniformOptions>(
+ new UniformOptions(binCount, minValue, exclusiveMaxValue));
+}
+
+Histogram::UniformOptions::UniformOptions(int binCount, float minValue, float exclusiveMaxValue)
+ : // Implicitly add 2 for the extra undeflow & overflow bins
+ mBinCount(binCount + 2),
+ mMinValue(minValue),
+ mExclusiveMaxValue(exclusiveMaxValue),
+ mBinSize((exclusiveMaxValue - minValue) / binCount) {
+}
+
+int Histogram::UniformOptions::getBinForSample(float sample) const {
+ if (sample < mMinValue) {
+ // goes to underflow
+ return 0;
+ } else if (sample >= mExclusiveMaxValue) {
+ // goes to overflow
+ return mBinCount - 1;
+ }
+ return (int)((sample - mMinValue) / mBinSize + 1);
+}
+
+Histogram::Histogram(const char* metricName, std::shared_ptr<BinOptions> binOptions)
+ : mMetricIdHash(farmhash::Fingerprint64(metricName, strlen(metricName))),
+ mBinOptions(std::move(binOptions)) {
+}
+
+void Histogram::logSample(float sample) const {
+ const int binIndex = mBinOptions->getBinForSample(sample);
+ stats_write(EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, /*count*/ 1, binIndex);
+}
+
+void Histogram::logSampleWithUid(int32_t uid, float sample) const {
+ const int binIndex = mBinOptions->getBinForSample(sample);
+ stats_write(EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, /*count*/ 1, binIndex, uid);
+}
+
+} // namespace expresslog
+} // namespace android
diff --git a/libstats/expresslog/include/Counter.h b/libstats/expresslog/include/Counter.h
new file mode 100644
index 0000000..8d0ab6a
--- /dev/null
+++ b/libstats/expresslog/include/Counter.h
@@ -0,0 +1,32 @@
+//
+// 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 <stdint.h>
+
+namespace android {
+namespace expresslog {
+
+/** Counter encapsulates StatsD write API calls */
+class Counter final {
+public:
+ static void logIncrement(const char* metricId, int64_t amount = 1);
+
+ static void logIncrementWithUid(const char* metricId, int32_t uid, int64_t amount = 1);
+};
+
+} // namespace expresslog
+} // namespace android
diff --git a/libstats/expresslog/include/Histogram.h b/libstats/expresslog/include/Histogram.h
new file mode 100644
index 0000000..49aee3d
--- /dev/null
+++ b/libstats/expresslog/include/Histogram.h
@@ -0,0 +1,86 @@
+//
+// 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 <stdint.h>
+
+#include <memory>
+
+namespace android {
+namespace expresslog {
+
+/** Histogram encapsulates StatsD write API calls */
+class Histogram final {
+public:
+ class BinOptions {
+ public:
+ virtual ~BinOptions() = default;
+ /**
+ * Returns bins count to be used by a Histogram
+ *
+ * @return bins count used to initialize Options, including overflow & underflow bins
+ */
+ virtual int getBinsCount() const = 0;
+
+ /**
+ * @return zero based index
+ * Calculates bin index for the input sample value
+ * index == 0 stands for underflow
+ * index == getBinsCount() - 1 stands for overflow
+ */
+ virtual int getBinForSample(float sample) const = 0;
+ };
+
+ /** Used by Histogram to map data sample to corresponding bin for uniform bins */
+ class UniformOptions : public BinOptions {
+ public:
+ static std::shared_ptr<UniformOptions> create(int binCount, float minValue,
+ float exclusiveMaxValue);
+
+ int getBinsCount() const override {
+ return mBinCount;
+ }
+
+ int getBinForSample(float sample) const override;
+
+ private:
+ UniformOptions(int binCount, float minValue, float exclusiveMaxValue);
+
+ const int mBinCount;
+ const float mMinValue;
+ const float mExclusiveMaxValue;
+ const float mBinSize;
+ };
+
+ Histogram(const char* metricName, std::shared_ptr<BinOptions> binOptions);
+
+ /**
+ * Logs increment sample count for automatically calculated bin
+ */
+ void logSample(float sample) const;
+
+ /**
+ * Logs increment sample count for automatically calculated bin with uid
+ */
+ void logSampleWithUid(int32_t uid, float sample) const;
+
+private:
+ const int64_t mMetricIdHash;
+ const std::shared_ptr<BinOptions> mBinOptions;
+};
+
+} // namespace expresslog
+} // namespace android
diff --git a/libstats/expresslog/tests/Histogram_test.cpp b/libstats/expresslog/tests/Histogram_test.cpp
new file mode 100644
index 0000000..813c997
--- /dev/null
+++ b/libstats/expresslog/tests/Histogram_test.cpp
@@ -0,0 +1,128 @@
+//
+// 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 "Histogram.h"
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace expresslog {
+
+#ifdef __ANDROID__
+TEST(UniformOptions, getBinsCount) {
+ const std::shared_ptr<Histogram::UniformOptions> options1(
+ Histogram::UniformOptions::create(1, 100, 1000));
+ ASSERT_EQ(3, options1->getBinsCount());
+
+ const std::shared_ptr<Histogram::UniformOptions> options10(
+ Histogram::UniformOptions::create(10, 100, 1000));
+ ASSERT_EQ(12, options10->getBinsCount());
+}
+
+TEST(UniformOptions, constructZeroBinsCount) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(0, 100, 1000));
+ ASSERT_EQ(nullptr, options);
+}
+
+TEST(UniformOptions, constructNegativeBinsCount) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(-1, 100, 1000));
+ ASSERT_EQ(nullptr, options);
+}
+
+TEST(UniformOptions, constructMaxValueLessThanMinValue) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(10, 1000, 100));
+ ASSERT_EQ(nullptr, options);
+}
+
+TEST(UniformOptions, testBinIndexForRangeEqual1) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(10, 1, 11));
+ for (int i = 0, bins = options->getBinsCount(); i < bins; i++) {
+ ASSERT_EQ(i, options->getBinForSample(i));
+ }
+}
+
+TEST(UniformOptions, testBinIndexForRangeEqual2) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(10, 1, 21));
+ for (int i = 0, bins = options->getBinsCount(); i < bins; i++) {
+ ASSERT_EQ(i, options->getBinForSample(i * 2));
+ ASSERT_EQ(i, options->getBinForSample(i * 2 - 1));
+ }
+}
+
+TEST(UniformOptions, testBinIndexForRangeEqual5) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(2, 0, 10));
+ ASSERT_EQ(4, options->getBinsCount());
+ for (int i = 0; i < 2; i++) {
+ for (int sample = 0; sample < 5; sample++) {
+ ASSERT_EQ(i + 1, options->getBinForSample(i * 5 + sample));
+ }
+ }
+}
+
+TEST(UniformOptions, testBinIndexForRangeEqual10) {
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(10, 1, 101));
+ ASSERT_EQ(0, options->getBinForSample(0));
+ ASSERT_EQ(options->getBinsCount() - 2, options->getBinForSample(100));
+ ASSERT_EQ(options->getBinsCount() - 1, options->getBinForSample(101));
+
+ const float binSize = (101 - 1) / 10.f;
+ for (int i = 1, bins = options->getBinsCount() - 1; i < bins; i++) {
+ ASSERT_EQ(i, options->getBinForSample(i * binSize));
+ }
+}
+
+TEST(UniformOptions, testBinIndexForRangeEqual90) {
+ const int binCount = 10;
+ const int minValue = 100;
+ const int maxValue = 100000;
+
+ const std::shared_ptr<Histogram::UniformOptions> options(
+ Histogram::UniformOptions::create(binCount, minValue, maxValue));
+
+ // logging underflow sample
+ ASSERT_EQ(0, options->getBinForSample(minValue - 1));
+
+ // logging overflow sample
+ ASSERT_EQ(binCount + 1, options->getBinForSample(maxValue));
+ ASSERT_EQ(binCount + 1, options->getBinForSample(maxValue + 1));
+
+ // logging min edge sample
+ ASSERT_EQ(1, options->getBinForSample(minValue));
+
+ // logging max edge sample
+ ASSERT_EQ(binCount, options->getBinForSample(maxValue - 1));
+
+ // logging single valid sample per bin
+ const int binSize = (maxValue - minValue) / binCount;
+
+ for (int i = 0; i < binCount; i++) {
+ ASSERT_EQ(i + 1, options->getBinForSample(minValue + binSize * i));
+ }
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace expresslog
+} // namespace android
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/libsystem/include/system/graphics-base-v1.2.h b/libsystem/include/system/graphics-base-v1.2.h
index 2194f5e..624912c 100644
--- a/libsystem/include/system/graphics-base-v1.2.h
+++ b/libsystem/include/system/graphics-base-v1.2.h
@@ -14,13 +14,17 @@
} android_hdr_v1_2_t;
typedef enum {
- HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* ((STANDARD_BT2020 | TRANSFER_SRGB) | RANGE_FULL) */,
+ HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL */,
HAL_DATASPACE_DYNAMIC_DEPTH = 4098 /* 0x1002 */,
HAL_DATASPACE_JPEG_APP_SEGMENTS = 4099 /* 0x1003 */,
HAL_DATASPACE_HEIF = 4100 /* 0x1004 */,
} android_dataspace_v1_2_t;
typedef enum {
+ HAL_COLOR_MODE_DISPLAY_BT2020 = 13,
+} android_color_mode_v1_2_t;
+
+typedef enum {
HAL_PIXEL_FORMAT_HSV_888 = 55 /* 0x37 */,
} android_pixel_format_v1_2_t;
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
index 5f472b2..1b41a6b 100644
--- a/libsysutils/Android.bp
+++ b/libsysutils/Android.bp
@@ -29,6 +29,10 @@
"liblog",
],
+ header_libs: [
+ "bpf_headers",
+ ],
+
export_include_dirs: ["include"],
tidy: true,
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 515cc10..cd9db54 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -37,10 +37,12 @@
#include <sys/utsname.h>
#include <android-base/parseint.h>
+#include <bpf/KernelUtils.h>
#include <log/log.h>
#include <sysutils/NetlinkEvent.h>
using android::base::ParseInt;
+using android::bpf::isKernel64Bit;
/* From kernel's net/netfilter/xt_quota2.c */
const int LOCAL_QLOG_NL_EVENT = 112;
@@ -138,60 +140,6 @@
static_assert(sizeof(ulog_packet_msg32_t) == 168);
static_assert(sizeof(ulog_packet_msg64_t) == 192);
-// Figure out the bitness of userspace.
-// Trivial and known at compile time.
-static bool isUserspace64bit(void) {
- return sizeof(long) == 8;
-}
-
-// Figure out the bitness of the kernel.
-static bool isKernel64Bit(void) {
- // a 64-bit userspace requires a 64-bit kernel
- if (isUserspace64bit()) return true;
-
- static bool init = false;
- static bool cache = false;
- if (init) return cache;
-
- // Retrieve current personality - on Linux this system call *cannot* fail.
- int p = personality(0xffffffff);
- // But if it does just assume kernel and userspace (which is 32-bit) match...
- if (p == -1) return false;
-
- // This will effectively mask out the bottom 8 bits, and switch to 'native'
- // personality, and then return the previous personality of this thread
- // (likely PER_LINUX or PER_LINUX32) with any extra options unmodified.
- int q = personality((p & ~PER_MASK) | PER_LINUX);
- // Per man page this theoretically could error out with EINVAL,
- // but kernel code analysis suggests setting PER_LINUX cannot fail.
- // Either way, assume kernel and userspace (which is 32-bit) match...
- if (q != p) return false;
-
- struct utsname u;
- (void)uname(&u); // only possible failure is EFAULT, but u is on stack.
-
- // Switch back to previous personality.
- // Theoretically could fail with EINVAL on arm64 with no 32-bit support,
- // but then we wouldn't have fetched 'p' from the kernel in the first place.
- // Either way there's nothing meaningul we can do in case of error.
- // Since PER_LINUX32 vs PER_LINUX only affects uname.machine it doesn't
- // really hurt us either. We're really just switching back to be 'clean'.
- (void)personality(p);
-
- // Possible values of utsname.machine observed on x86_64 desktop (arm via qemu):
- // x86_64 i686 aarch64 armv7l
- // additionally observed on arm device:
- // armv8l
- // presumably also might just be possible:
- // i386 i486 i586
- // and there might be other weird arm32 cases.
- // We note that the 64 is present in both 64-bit archs,
- // and in general is likely to be present in only 64-bit archs.
- cache = !!strstr(u.machine, "64");
- init = true;
- return cache;
-}
-
/******************************************************************************/
NetlinkEvent::NetlinkEvent() {
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 26e1597..162f0f4 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -21,11 +21,13 @@
vendor_ramdisk_available: true,
host_supported: true,
native_bridge_supported: true,
+ defaults: [
+ "apex-lowest-min-sdk-version",
+ ],
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
],
- min_sdk_version: "apex_inherit",
header_libs: [
"libbase_headers",
@@ -124,7 +126,10 @@
cc_defaults {
name: "libutils_impl_defaults",
- defaults: ["libutils_defaults"],
+ defaults: [
+ "libutils_defaults",
+ "apex-lowest-min-sdk-version",
+ ],
native_bridge_supported: true,
srcs: [
@@ -167,13 +172,8 @@
"//apex_available:anyapex",
"//apex_available:platform",
],
- min_sdk_version: "apex_inherit",
afdo: true,
-
- header_abi_checker: {
- diff_flags: ["-allow-adding-removing-weak-symbols"],
- },
}
cc_library {
@@ -184,6 +184,12 @@
enabled: true,
support_system_process: true,
},
+
+ header_abi_checker: {
+ // AFDO affects weak symbols.
+ diff_flags: ["-allow-adding-removing-weak-symbols"],
+ ref_dump_dirs: ["abi-dumps"],
+ },
}
cc_library {
diff --git a/libutils/Errors.cpp b/libutils/Errors.cpp
index 74f3bef..dfb4d9b 100644
--- a/libutils/Errors.cpp
+++ b/libutils/Errors.cpp
@@ -15,6 +15,8 @@
*/
#include <utils/Errors.h>
+#include <string.h>
+
namespace android {
std::string statusToString(status_t s) {
diff --git a/libutils/LruCache_test.cpp b/libutils/LruCache_test.cpp
index 8b16947..5cd3cbb 100644
--- a/libutils/LruCache_test.cpp
+++ b/libutils/LruCache_test.cpp
@@ -29,6 +29,8 @@
struct ComplexKey {
int k;
+ explicit ComplexKey() : k(0) { instanceCount += 1; }
+
explicit ComplexKey(int k) : k(k) {
instanceCount += 1;
}
@@ -57,6 +59,8 @@
struct ComplexValue {
int v;
+ explicit ComplexValue() : v(0) { instanceCount += 1; }
+
explicit ComplexValue(int v) : v(v) {
instanceCount += 1;
}
@@ -83,10 +87,9 @@
struct KeyFailsOnCopy : public ComplexKey {
public:
- KeyFailsOnCopy(const KeyFailsOnCopy& key) : ComplexKey(key) {
- ADD_FAILURE();
- }
- KeyFailsOnCopy(int key) : ComplexKey(key) { }
+ KeyFailsOnCopy() : ComplexKey() {}
+ KeyFailsOnCopy(const KeyFailsOnCopy& key) : ComplexKey(key) { ADD_FAILURE(); }
+ KeyFailsOnCopy(int key) : ComplexKey(key) {}
};
} // namespace
diff --git a/libutils/ProcessCallStack_fuzz.cpp b/libutils/ProcessCallStack_fuzz.cpp
index 30136cd..552a11e 100644
--- a/libutils/ProcessCallStack_fuzz.cpp
+++ b/libutils/ProcessCallStack_fuzz.cpp
@@ -44,7 +44,7 @@
dataProvider->ConsumeRandomLengthString(MAX_NAME_SIZE).append(std::to_string(i));
std::thread th = std::thread(loop);
pthread_setname_np(th.native_handle(), threadName.c_str());
- threads.push_back(move(th));
+ threads.push_back(std::move(th));
}
// Collect thread information
diff --git a/libutils/RefBase_fuzz.cpp b/libutils/RefBase_fuzz.cpp
index 69288b3..8291be9 100644
--- a/libutils/RefBase_fuzz.cpp
+++ b/libutils/RefBase_fuzz.cpp
@@ -177,7 +177,7 @@
uint8_t opCount = dataProvider->ConsumeIntegralInRange<uint8_t>(1, kMaxOperations);
std::vector<uint8_t> threadOperations = dataProvider->ConsumeBytes<uint8_t>(opCount);
std::thread tmpThread = std::thread(loop, threadOperations);
- threads.push_back(move(tmpThread));
+ threads.push_back(std::move(tmpThread));
}
for (auto& th : threads) {
diff --git a/libutils/RefBase_test.cpp b/libutils/RefBase_test.cpp
index aed3b9b..d675598 100644
--- a/libutils/RefBase_test.cpp
+++ b/libutils/RefBase_test.cpp
@@ -28,7 +28,7 @@
using namespace android;
-static constexpr int NITERS = 1000000;
+static constexpr int NITERS = 500000;
static constexpr int INITIAL_STRONG_VALUE = 1 << 28; // Mirroring RefBase definition.
diff --git a/libutils/Unicode_test.cpp b/libutils/Unicode_test.cpp
index 8b994d9..7969525 100644
--- a/libutils/Unicode_test.cpp
+++ b/libutils/Unicode_test.cpp
@@ -35,86 +35,208 @@
}
char16_t const * const kSearchString = u"I am a leaf on the wind.";
+
+ constexpr static size_t BUFSIZE = 64; // large enough for all tests
+
+ void TestUTF8toUTF16(std::initializer_list<uint8_t> input,
+ std::initializer_list<char16_t> expect,
+ const char* err_msg_length = "",
+ ssize_t expected_length = 0) {
+ uint8_t empty_str[] = {};
+ char16_t output[BUFSIZE];
+
+ const size_t inlen = input.size(), outlen = expect.size();
+ ASSERT_LT(outlen, BUFSIZE);
+
+ const uint8_t *input_data = inlen ? std::data(input) : empty_str;
+ ssize_t measured = utf8_to_utf16_length(input_data, inlen);
+ EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+ utf8_to_utf16(input_data, inlen, output, outlen + 1);
+ for (size_t i = 0; i < outlen; i++) {
+ EXPECT_EQ(std::data(expect)[i], output[i]);
+ }
+ EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+ }
+
+ void TestUTF16toUTF8(std::initializer_list<char16_t> input,
+ std::initializer_list<char> expect,
+ const char* err_msg_length = "",
+ ssize_t expected_length = 0) {
+ char16_t empty_str[] = {};
+ char output[BUFSIZE];
+
+ const size_t inlen = input.size(), outlen = expect.size();
+ ASSERT_LT(outlen, BUFSIZE);
+
+ const char16_t *input_data = inlen ? std::data(input) : empty_str;
+ ssize_t measured = utf16_to_utf8_length(input_data, inlen);
+ EXPECT_EQ(expected_length ? : (ssize_t)outlen, measured) << err_msg_length;
+
+ utf16_to_utf8(input_data, inlen, output, outlen + 1);
+ for (size_t i = 0; i < outlen; i++) {
+ EXPECT_EQ(std::data(expect)[i], output[i]);
+ }
+ EXPECT_EQ(0, output[outlen]) << "should be null terminated";
+ }
};
TEST_F(UnicodeTest, UTF8toUTF16ZeroLength) {
- ssize_t measured;
-
- const uint8_t str[] = { };
-
- measured = utf8_to_utf16_length(str, 0);
- EXPECT_EQ(0, measured)
- << "Zero length input should return zero length output.";
+ TestUTF8toUTF16({}, {},
+ "Zero length input should return zero length output.");
}
-TEST_F(UnicodeTest, UTF8toUTF16ASCIILength) {
- ssize_t measured;
-
- // U+0030 or ASCII '0'
- const uint8_t str[] = { 0x30 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(1, measured)
- << "ASCII glyphs should have a length of 1 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16ASCII) {
+ TestUTF8toUTF16(
+ { 0x30 }, // U+0030 or ASCII '0'
+ { 0x0030 },
+ "ASCII codepoints should have a length of 1 char16_t");
}
-TEST_F(UnicodeTest, UTF8toUTF16Plane1Length) {
- ssize_t measured;
-
- // U+2323 SMILE
- const uint8_t str[] = { 0xE2, 0x8C, 0xA3 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(1, measured)
- << "Plane 1 glyphs should have a length of 1 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16Plane1) {
+ TestUTF8toUTF16(
+ { 0xE2, 0x8C, 0xA3 }, // U+2323 SMILE
+ { 0x2323 },
+ "Plane 1 codepoints should have a length of 1 char16_t");
}
-TEST_F(UnicodeTest, UTF8toUTF16SurrogateLength) {
- ssize_t measured;
-
- // U+10000
- const uint8_t str[] = { 0xF0, 0x90, 0x80, 0x80 };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(2, measured)
- << "Surrogate pairs should have a length of 2 char16_t";
+TEST_F(UnicodeTest, UTF8toUTF16Surrogate) {
+ TestUTF8toUTF16(
+ { 0xF0, 0x90, 0x80, 0x80 }, // U+10000
+ { 0xD800, 0xDC00 },
+ "Surrogate pairs should have a length of 2 char16_t");
}
TEST_F(UnicodeTest, UTF8toUTF16TruncatedUTF8) {
- ssize_t measured;
-
- // Truncated U+2323 SMILE
- // U+2323 SMILE
- const uint8_t str[] = { 0xE2, 0x8C };
-
- measured = utf8_to_utf16_length(str, sizeof(str));
- EXPECT_EQ(-1, measured)
- << "Truncated UTF-8 should return -1 to indicate invalid";
+ TestUTF8toUTF16(
+ { 0xE2, 0x8C }, // Truncated U+2323 SMILE
+ { }, // Conversion should still work but produce nothing
+ "Truncated UTF-8 should return -1 to indicate invalid",
+ -1);
}
TEST_F(UnicodeTest, UTF8toUTF16Normal) {
- const uint8_t str[] = {
- 0x30, // U+0030, 1 UTF-16 character
- 0xC4, 0x80, // U+0100, 1 UTF-16 character
- 0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
+ TestUTF8toUTF16({
+ 0x30, // U+0030, 1 UTF-16 character
+ 0xC4, 0x80, // U+0100, 1 UTF-16 character
+ 0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
0xF0, 0x90, 0x80, 0x80, // U+10000, 2 UTF-16 character
- };
+ }, {
+ 0x0030,
+ 0x0100,
+ 0x2323,
+ 0xD800, 0xDC00
+ });
+}
- char16_t output[1 + 1 + 1 + 2 + 1]; // Room for null
+TEST_F(UnicodeTest, UTF8toUTF16Invalid) {
+ // TODO: The current behavior of utf8_to_utf16 is to treat invalid
+ // leading byte (>= 0xf8) as a 4-byte UTF8 sequence, and to treat
+ // invalid trailing byte(s) (i.e. bytes not having MSB set) as if
+ // they are valid and do the normal conversion. However, a better
+ // handling would be to treat invalid sequences as errors, such
+ // cases need to be reported and invalid characters (e.g. U+FFFD)
+ // could be produced at the place of error. Until a fix is ready
+ // and compatibility is not an issue, we will keep testing the
+ // current behavior
+ TestUTF8toUTF16({
+ 0xf8, // invalid leading byte
+ 0xc4, 0x00, // U+0100 with invalid trailing byte
+ 0xe2, 0x0c, 0xa3, // U+2323 with invalid trailing bytes
+ 0xf0, 0x10, 0x00, 0x00, // U+10000 with invalid trailing bytes
+ }, {
+ 0x4022, // invalid leading byte (>=0xfc) is treated
+ // as valid for 4-byte UTF8 sequence
+ 0x000C,
+ 0x00A3, // invalid leadnig byte (b'10xxxxxx) is
+ // treated as valid single UTF-8 byte
+ 0xD800, // invalid trailing bytes are treated
+ 0xDC00, // as valid bytes and follow normal
+ });
+}
- utf8_to_utf16(str, sizeof(str), output, sizeof(output) / sizeof(output[0]));
+TEST_F(UnicodeTest, UTF16toUTF8ZeroLength) {
+ // TODO: The current behavior of utf16_to_utf8_length() is that
+ // it returns -1 if the input is a zero length UTF16 string.
+ // This is inconsistent with utf8_to_utf16_length() where a zero
+ // length string returns 0. However, to fix the current behavior,
+ // we could have compatibility issue. Until then, we will keep
+ // testing the current behavior
+ TestUTF16toUTF8({}, {},
+ "Zero length UTF16 input should return length of -1.", -1);
+}
- EXPECT_EQ(0x0030, output[0])
- << "should be U+0030";
- EXPECT_EQ(0x0100, output[1])
- << "should be U+0100";
- EXPECT_EQ(0x2323, output[2])
- << "should be U+2323";
- EXPECT_EQ(0xD800, output[3])
- << "should be first half of surrogate U+10000";
- EXPECT_EQ(0xDC00, output[4])
- << "should be second half of surrogate U+10000";
- EXPECT_EQ(0, output[5]) << "should be null terminated";
+TEST_F(UnicodeTest, UTF16toUTF8ASCII) {
+ TestUTF16toUTF8(
+ { 0x0030 }, // U+0030 or ASCII '0'
+ { '\x30' },
+ "ASCII codepoints in UTF16 should give a length of 1 in UTF8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Plane1) {
+ TestUTF16toUTF8(
+ { 0x2323 }, // U+2323 SMILE
+ { '\xE2', '\x8C', '\xA3' },
+ "Plane 1 codepoints should have a length of 3 char in UTF-8");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Surrogate) {
+ TestUTF16toUTF8(
+ { 0xD800, 0xDC00 }, // U+10000
+ { '\xF0', '\x90', '\x80', '\x80' },
+ "Surrogate pairs should have a length of 4 chars");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8UnpairedSurrogate) {
+ TestUTF16toUTF8(
+ { 0xD800 }, // U+10000 with high surrogate pair only
+ { }, // Unpaired surrogate should be ignored
+ "A single unpaired high surrogate should have a length of 0 chars");
+
+ TestUTF16toUTF8(
+ { 0xDC00 }, // U+10000 with low surrogate pair only
+ { }, // Unpaired surrogate should be ignored
+ "A single unpaired low surrogate should have a length of 0 chars");
+
+ TestUTF16toUTF8(
+ // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+ { 0x0030, 0x0100, 0xDC00, 0x2323 },
+ { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+ "Unpaired high surrogate should be skipped in the middle");
+
+ TestUTF16toUTF8(
+ // U+0030, U+0100, U+10000 with high surrogate pair only, U+2323
+ { 0x0030, 0x0100, 0xDC00, 0x2323 },
+ { '\x30', '\xC4', '\x80', '\xE2', '\x8C', '\xA3' },
+ "Unpaired low surrogate should be skipped in the middle");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8CorrectInvalidSurrogate) {
+ // http://b/29250543
+ // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the
+ // first character in the pair and handling the rest correctly.
+ TestUTF16toUTF8(
+ { 0xD841, 0xD841, 0xDC41 }, // U+20441
+ { '\xF0', '\xA0', '\x91', '\x81' },
+ "Invalid start for a surrogate pair should be ignored");
+}
+
+TEST_F(UnicodeTest, UTF16toUTF8Normal) {
+ TestUTF16toUTF8({
+ 0x0024, // U+0024 ($) --> 0x24, 1 UTF-8 byte
+ 0x00A3, // U+00A3 (£) --> 0xC2 0xA3, 2 UTF-8 bytes
+ 0x0939, // U+0939 (ह) --> 0xE0 0xA4 0xB9, 3 UTF-8 bytes
+ 0x20AC, // U+20AC (€) --> 0xE2 0x82 0xAC, 3 UTF-8 bytes
+ 0xD55C, // U+D55C (한)--> 0xED 0x95 0x9C, 3 UTF-8 bytes
+ 0xD801, 0xDC37, // U+10437 (𐐷) --> 0xF0 0x90 0x90 0xB7, 4 UTF-8 bytes
+ }, {
+ '\x24',
+ '\xC2', '\xA3',
+ '\xE0', '\xA4', '\xB9',
+ '\xE2', '\x82', '\xAC',
+ '\xED', '\x95', '\x9C',
+ '\xF0', '\x90', '\x90', '\xB7',
+ });
}
TEST_F(UnicodeTest, strstr16EmptyTarget) {
diff --git a/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump b/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump
new file mode 100644
index 0000000..c89af9e
--- /dev/null
+++ b/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump
@@ -0,0 +1,15553 @@
+{
+ "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_outside_system/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 2,
+ "linker_set_key" : "_ZTIA1_Ds",
+ "name" : "char16_t[1]",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIA1_Ds",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIA20_c",
+ "name" : "char[20]",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIA20_c",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIA5121_h",
+ "name" : "unsigned char[5121]",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIA5121_h",
+ "size" : 5121,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIA8_j",
+ "name" : "unsigned int[8]",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIA8_j",
+ "size" : 32,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "linker_set_key" : "_ZTIA_f",
+ "name" : "float[]",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIA_f",
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ }
+ ],
+ "builtin_types" :
+ [
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIDi",
+ "name" : "char32_t",
+ "referenced_type" : "_ZTIDi",
+ "self_type" : "_ZTIDi",
+ "size" : 4
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIDn",
+ "name" : "std::nullptr_t",
+ "referenced_type" : "_ZTIDn",
+ "self_type" : "_ZTIDn",
+ "size" : 8
+ },
+ {
+ "alignment" : 2,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIDs",
+ "name" : "char16_t",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIDs",
+ "size" : 2
+ },
+ {
+ "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" : 8,
+ "linker_set_key" : "_ZTId",
+ "name" : "double",
+ "referenced_type" : "_ZTId",
+ "self_type" : "_ZTId",
+ "size" : 8
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIf",
+ "name" : "float",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIf",
+ "size" : 4
+ },
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIh",
+ "name" : "unsigned char",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIh",
+ "size" : 1
+ },
+ {
+ "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
+ },
+ {
+ "alignment" : 2,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIs",
+ "name" : "short",
+ "referenced_type" : "_ZTIs",
+ "self_type" : "_ZTIs",
+ "size" : 2
+ },
+ {
+ "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" : "_Z24androidCreateThreadGetIDPFiPvES_PS_"
+ },
+ {
+ "name" : "_ZN7android10LogPrinter8printRawEPKc"
+ },
+ {
+ "name" : "_ZN7android10LogPrinter9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android10LogPrinterC1EPKc19android_LogPriorityS2_b"
+ },
+ {
+ "name" : "_ZN7android10LogPrinterC2EPKc19android_LogPriorityS2_b"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl11appendArrayEPKvm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl11setCapacityEm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl12appendVectorERKS0_"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13editArrayImplEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13finish_vectorEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13insertArrayAtEPKvmm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13removeItemsAtEmm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl14insertVectorAtERKS0_m"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl15release_storageEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl16editItemLocationEm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl3addEPKv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl3addEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl3popEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4pushEPKv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4pushEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4sortEPFiPKvS2_E"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4sortEPFiPKvS2_PvES3_"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl5_growEmm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl5clearEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl6resizeEm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl7_shrinkEmm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl8insertAtEPKvmm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl8insertAtEmm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl9replaceAtEPKvm"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl9replaceAtEm"
+ },
+ {
+ "name" : "_ZN7android10VectorImplC2ERKS0_"
+ },
+ {
+ "name" : "_ZN7android10VectorImplC2Emj"
+ },
+ {
+ "name" : "_ZN7android10VectorImplD0Ev"
+ },
+ {
+ "name" : "_ZN7android10VectorImplD1Ev"
+ },
+ {
+ "name" : "_ZN7android10VectorImplD2Ev"
+ },
+ {
+ "name" : "_ZN7android10VectorImplaSERKS0_"
+ },
+ {
+ "name" : "_ZN7android11uptimeNanosEv"
+ },
+ {
+ "name" : "_ZN7android12NativeHandle6createEP13native_handleb"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleC1EP13native_handleb"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleC2EP13native_handleb"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleD1Ev"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleD2Ev"
+ },
+ {
+ "name" : "_ZN7android12SharedBuffer5allocEm"
+ },
+ {
+ "name" : "_ZN7android12SharedBuffer7deallocEPKS0_"
+ },
+ {
+ "name" : "_ZN7android12uptimeMillisEv"
+ },
+ {
+ "name" : "_ZN7android13PrefixPrinter9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android13PrefixPrinterC1ERNS_7PrinterEPKc"
+ },
+ {
+ "name" : "_ZN7android13PrefixPrinterC2ERNS_7PrinterEPKc"
+ },
+ {
+ "name" : "_ZN7android14LooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZN7android14LooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZN7android14LooperCallbackD2Ev"
+ },
+ {
+ "name" : "_ZN7android14MessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZN7android14MessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZN7android14MessageHandlerD2Ev"
+ },
+ {
+ "name" : "_ZN7android14String8Printer9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android14String8PrinterC1EPNS_7String8EPKc"
+ },
+ {
+ "name" : "_ZN7android14String8PrinterC2EPNS_7String8EPKc"
+ },
+ {
+ "name" : "_ZN7android14sp_report_raceEv"
+ },
+ {
+ "name" : "_ZN7android14statusToStringEi"
+ },
+ {
+ "name" : "_ZN7android15elapsedRealtimeEv"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl3addEPKv"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl5mergeERKNS_10VectorImplE"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl5mergeERKS0_"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl6removeEPKv"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplC2ERKNS_10VectorImplE"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplC2Emj"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplD0Ev"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplD1Ev"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplD2Ev"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplaSERKS0_"
+ },
+ {
+ "name" : "_ZN7android17JenkinsHashWhitenEj"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandler13handleMessageERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerC1ERKNS_2wpINS_14MessageHandlerEEE"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerC2ERKNS_2wpINS_14MessageHandlerEEE"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerD2Ev"
+ },
+ {
+ "name" : "_ZN7android19JenkinsHashMixBytesEjPKhm"
+ },
+ {
+ "name" : "_ZN7android19elapsedRealtimeNanoEv"
+ },
+ {
+ "name" : "_ZN7android20JenkinsHashMixShortsEjPKtm"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallback11handleEventEiiPv"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackC1EPFiiiPvE"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackC2EPFiiiPvE"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackD2Ev"
+ },
+ {
+ "name" : "_ZN7android21report_sysprop_changeEv"
+ },
+ {
+ "name" : "_ZN7android23sp_report_stack_pointerEv"
+ },
+ {
+ "name" : "_ZN7android27add_sysprop_change_callbackEPFvvEi"
+ },
+ {
+ "name" : "_ZN7android30get_report_sysprop_change_funcEv"
+ },
+ {
+ "name" : "_ZN7android47LightRefBase_reportIncStrongRequireStrongFailedEPKv"
+ },
+ {
+ "name" : "_ZN7android6Looper10initTLSKeyEv"
+ },
+ {
+ "name" : "_ZN7android6Looper11sendMessageERKNS_2spINS_14MessageHandlerEEERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android6Looper12getForThreadEv"
+ },
+ {
+ "name" : "_ZN7android6Looper12setForThreadERKNS_2spIS0_EE"
+ },
+ {
+ "name" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEE"
+ },
+ {
+ "name" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEEi"
+ },
+ {
+ "name" : "_ZN7android6Looper16threadDestructorEPv"
+ },
+ {
+ "name" : "_ZN7android6Looper17sendMessageAtTimeElRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android6Looper18rebuildEpollLockedEv"
+ },
+ {
+ "name" : "_ZN7android6Looper18sendMessageDelayedElRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android6Looper26removeSequenceNumberLockedEm"
+ },
+ {
+ "name" : "_ZN7android6Looper26scheduleEpollRebuildLockedEv"
+ },
+ {
+ "name" : "_ZN7android6Looper4wakeEv"
+ },
+ {
+ "name" : "_ZN7android6Looper5addFdEiiiPFiiiPvES1_"
+ },
+ {
+ "name" : "_ZN7android6Looper5addFdEiiiRKNS_2spINS_14LooperCallbackEEEPv"
+ },
+ {
+ "name" : "_ZN7android6Looper6awokenEv"
+ },
+ {
+ "name" : "_ZN7android6Looper7pollAllEiPiS1_PPv"
+ },
+ {
+ "name" : "_ZN7android6Looper7prepareEi"
+ },
+ {
+ "name" : "_ZN7android6Looper8pollOnceEiPiS1_PPv"
+ },
+ {
+ "name" : "_ZN7android6Looper8removeFdEi"
+ },
+ {
+ "name" : "_ZN7android6Looper9pollInnerEi"
+ },
+ {
+ "name" : "_ZN7android6LooperC1Eb"
+ },
+ {
+ "name" : "_ZN7android6LooperC2Eb"
+ },
+ {
+ "name" : "_ZN7android6LooperD0Ev"
+ },
+ {
+ "name" : "_ZN7android6LooperD1Ev"
+ },
+ {
+ "name" : "_ZN7android6LooperD2Ev"
+ },
+ {
+ "name" : "_ZN7android6Thread10readyToRunEv"
+ },
+ {
+ "name" : "_ZN7android6Thread11_threadLoopEPv"
+ },
+ {
+ "name" : "_ZN7android6Thread11requestExitEv"
+ },
+ {
+ "name" : "_ZN7android6Thread18requestExitAndWaitEv"
+ },
+ {
+ "name" : "_ZN7android6Thread3runEPKcim"
+ },
+ {
+ "name" : "_ZN7android6Thread4joinEv"
+ },
+ {
+ "name" : "_ZN7android6ThreadC2Eb"
+ },
+ {
+ "name" : "_ZN7android6ThreadD0Ev"
+ },
+ {
+ "name" : "_ZN7android6ThreadD1Ev"
+ },
+ {
+ "name" : "_ZN7android6ThreadD2Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMap6adviseENS0_9MapAdviceE"
+ },
+ {
+ "name" : "_ZN7android7FileMap6createEPKcilmb"
+ },
+ {
+ "name" : "_ZN7android7FileMapC1EOS0_"
+ },
+ {
+ "name" : "_ZN7android7FileMapC1Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapC2EOS0_"
+ },
+ {
+ "name" : "_ZN7android7FileMapC2Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapD1Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapD2Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapaSEOS0_"
+ },
+ {
+ "name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "name" : "_ZN7android7PrinterC2Ev"
+ },
+ {
+ "name" : "_ZN7android7PrinterD0Ev"
+ },
+ {
+ "name" : "_ZN7android7PrinterD1Ev"
+ },
+ {
+ "name" : "_ZN7android7PrinterD2Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "name" : "_ZN7android7RefBase10renameRefsEmRKNS_16ReferenceRenamerE"
+ },
+ {
+ "name" : "_ZN7android7RefBase11renameRefIdEPNS0_12weakref_typeEPKvS4_"
+ },
+ {
+ "name" : "_ZN7android7RefBase11renameRefIdEPS0_PKvS3_"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type14attemptIncWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type16attemptIncStrongEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type18incWeakRequireWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type7decWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type7incWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type7trackMeEbb"
+ },
+ {
+ "name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase20extendObjectLifetimeEi"
+ },
+ {
+ "name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBaseC1Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseC2Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseD0Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseD1Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseD2Ev"
+ },
+ {
+ "name" : "_ZN7android7String810appendPathEPKc"
+ },
+ {
+ "name" : "_ZN7android7String810lockBufferEm"
+ },
+ {
+ "name" : "_ZN7android7String811real_appendEPKcm"
+ },
+ {
+ "name" : "_ZN7android7String812appendFormatEPKcz"
+ },
+ {
+ "name" : "_ZN7android7String812unlockBufferEm"
+ },
+ {
+ "name" : "_ZN7android7String812unlockBufferEv"
+ },
+ {
+ "name" : "_ZN7android7String813appendFormatVEPKcSt9__va_list"
+ },
+ {
+ "name" : "_ZN7android7String816convertToResPathEv"
+ },
+ {
+ "name" : "_ZN7android7String85clearEv"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKDim"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKDsm"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKc"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKcm"
+ },
+ {
+ "name" : "_ZN7android7String85setToERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String86appendEPKc"
+ },
+ {
+ "name" : "_ZN7android7String86appendEPKcm"
+ },
+ {
+ "name" : "_ZN7android7String86appendERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String86formatEPKcz"
+ },
+ {
+ "name" : "_ZN7android7String87formatVEPKcSt9__va_list"
+ },
+ {
+ "name" : "_ZN7android7String87toLowerEv"
+ },
+ {
+ "name" : "_ZN7android7String89removeAllEPKc"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDi"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDim"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDs"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDsm"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKc"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKcm"
+ },
+ {
+ "name" : "_ZN7android7String8C1ERKNS_8String16E"
+ },
+ {
+ "name" : "_ZN7android7String8C1ERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String8C1Ev"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDi"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDim"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDs"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDsm"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKc"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKcm"
+ },
+ {
+ "name" : "_ZN7android7String8C2ERKNS_8String16E"
+ },
+ {
+ "name" : "_ZN7android7String8C2ERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String8C2Ev"
+ },
+ {
+ "name" : "_ZN7android7String8D1Ev"
+ },
+ {
+ "name" : "_ZN7android7String8D2Ev"
+ },
+ {
+ "name" : "_ZN7android8String1610editResizeEm"
+ },
+ {
+ "name" : "_ZN7android8String1610replaceAllEDsDs"
+ },
+ {
+ "name" : "_ZN7android8String1613allocFromUTF8EPKcm"
+ },
+ {
+ "name" : "_ZN7android8String1614allocFromUTF16EPKDsm"
+ },
+ {
+ "name" : "_ZN7android8String164editEv"
+ },
+ {
+ "name" : "_ZN7android8String165allocEm"
+ },
+ {
+ "name" : "_ZN7android8String165setToEPKDs"
+ },
+ {
+ "name" : "_ZN7android8String165setToEPKDsm"
+ },
+ {
+ "name" : "_ZN7android8String165setToERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String165setToERKS0_mm"
+ },
+ {
+ "name" : "_ZN7android8String166appendEPKDsm"
+ },
+ {
+ "name" : "_ZN7android8String166appendERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String166insertEmPKDs"
+ },
+ {
+ "name" : "_ZN7android8String166insertEmPKDsm"
+ },
+ {
+ "name" : "_ZN7android8String167acquireEv"
+ },
+ {
+ "name" : "_ZN7android8String167releaseEv"
+ },
+ {
+ "name" : "_ZN7android8String16C1EOS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKDs"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKDsm"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKc"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKcm"
+ },
+ {
+ "name" : "_ZN7android8String16C1ERKNS_7String8E"
+ },
+ {
+ "name" : "_ZN7android8String16C1ERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C1ERKS0_mm"
+ },
+ {
+ "name" : "_ZN7android8String16C1Ev"
+ },
+ {
+ "name" : "_ZN7android8String16C2EOS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKDs"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKDsm"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKc"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKcm"
+ },
+ {
+ "name" : "_ZN7android8String16C2ERKNS_7String8E"
+ },
+ {
+ "name" : "_ZN7android8String16C2ERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C2ERKS0_mm"
+ },
+ {
+ "name" : "_ZN7android8String16C2Ev"
+ },
+ {
+ "name" : "_ZN7android8String16D1Ev"
+ },
+ {
+ "name" : "_ZN7android8String16D2Ev"
+ },
+ {
+ "name" : "_ZN7android8String16aSEOS0_"
+ },
+ {
+ "name" : "_ZN7android9FdPrinter9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android9FdPrinterC1EijPKc"
+ },
+ {
+ "name" : "_ZN7android9FdPrinterC2EijPKc"
+ },
+ {
+ "name" : "_ZN7android9StopWatch5resetEv"
+ },
+ {
+ "name" : "_ZN7android9StopWatchC1EPKci"
+ },
+ {
+ "name" : "_ZN7android9StopWatchC2EPKci"
+ },
+ {
+ "name" : "_ZN7android9StopWatchD1Ev"
+ },
+ {
+ "name" : "_ZN7android9StopWatchD2Ev"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer12fromContentsERKNS_7String8EPKcPPS0_"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer14skipDelimitersEPKc"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer4openERKNS_7String8EPPS0_"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer8nextLineEv"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer9nextTokenEPKc"
+ },
+ {
+ "name" : "_ZN7android9TokenizerC1ERKNS_7String8EPNS_7FileMapEPcbm"
+ },
+ {
+ "name" : "_ZN7android9TokenizerC2ERKNS_7String8EPNS_7FileMapEPcbm"
+ },
+ {
+ "name" : "_ZN7android9TokenizerD1Ev"
+ },
+ {
+ "name" : "_ZN7android9TokenizerD2Ev"
+ },
+ {
+ "name" : "_ZNK7android10VectorImpl12itemLocationEm"
+ },
+ {
+ "name" : "_ZNK7android10VectorImpl8capacityEv"
+ },
+ {
+ "name" : "_ZNK7android10VectorImpl8itemSizeEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer10editResizeEm"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer11attemptEditEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer4editEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer5resetEm"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer7acquireEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer7releaseEj"
+ },
+ {
+ "name" : "_ZNK7android16SortedVectorImpl13_indexOrderOfEPKvPm"
+ },
+ {
+ "name" : "_ZNK7android16SortedVectorImpl7indexOfEPKv"
+ },
+ {
+ "name" : "_ZNK7android16SortedVectorImpl7orderOfEPKv"
+ },
+ {
+ "name" : "_ZNK7android6Looper20getAllowNonCallbacksEv"
+ },
+ {
+ "name" : "_ZNK7android6Looper7Request14getEpollEventsEv"
+ },
+ {
+ "name" : "_ZNK7android6Looper9isPollingEv"
+ },
+ {
+ "name" : "_ZNK7android6Thread11exitPendingEv"
+ },
+ {
+ "name" : "_ZNK7android6Thread6getTidEv"
+ },
+ {
+ "name" : "_ZNK7android6Thread9isRunningEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE10do_destroyEPvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE12do_constructEPvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE15do_move_forwardEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE16do_move_backwardEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE7do_copyEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE8do_splatEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE10do_destroyEPvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE12do_constructEPvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE15do_move_forwardEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE16do_move_backwardEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE7do_copyEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE8do_splatEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE10do_destroyEPvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE12do_constructEPvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE15do_move_forwardEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE16do_move_backwardEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE7do_copyEPvPKvm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE8do_splatEPvPKvm"
+ },
+ {
+ "name" : "_ZNK7android7RefBase10createWeakEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase11getWeakRefsEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase12weakref_type12getWeakCountEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase12weakref_type7refBaseEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase12weakref_type9printRefsEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase14forceIncStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase14getStrongCountEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase22incStrongRequireStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase9decStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase9incStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7String810getPathDirEv"
+ },
+ {
+ "name" : "_ZNK7android7String811getBasePathEv"
+ },
+ {
+ "name" : "_ZNK7android7String811getPathLeafEv"
+ },
+ {
+ "name" : "_ZNK7android7String814find_extensionEv"
+ },
+ {
+ "name" : "_ZNK7android7String816getPathExtensionEv"
+ },
+ {
+ "name" : "_ZNK7android7String84findEPKcm"
+ },
+ {
+ "name" : "_ZNK7android7String86lengthEv"
+ },
+ {
+ "name" : "_ZNK7android7String88walkPathEPS0_"
+ },
+ {
+ "name" : "_ZNK7android8String1610startsWithEPKDs"
+ },
+ {
+ "name" : "_ZNK7android8String1610startsWithERKS0_"
+ },
+ {
+ "name" : "_ZNK7android8String1614isStaticStringEv"
+ },
+ {
+ "name" : "_ZNK7android8String1616staticStringSizeEv"
+ },
+ {
+ "name" : "_ZNK7android8String164sizeEv"
+ },
+ {
+ "name" : "_ZNK7android8String168containsEPKDs"
+ },
+ {
+ "name" : "_ZNK7android8String168findLastEDs"
+ },
+ {
+ "name" : "_ZNK7android8String169findFirstEDs"
+ },
+ {
+ "name" : "_ZNK7android9StopWatch11elapsedTimeEv"
+ },
+ {
+ "name" : "_ZNK7android9StopWatch4nameEv"
+ },
+ {
+ "name" : "_ZNK7android9Tokenizer11getLocationEv"
+ },
+ {
+ "name" : "_ZNK7android9Tokenizer19peekRemainderOfLineEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIimEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE14__erase_uniqueIiEEmRKT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIimEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE25__emplace_unique_key_argsIiJRiRKmEEENS_4pairINS_15__hash_iteratorIPNS_11__hash_nodeIS2_PvEEEEbEERKT_DpOT0_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIimEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE6rehashEm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIimEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE6removeENS_21__hash_const_iteratorIPNS_11__hash_nodeIS2_PvEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIimEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE8__rehashEm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeImN7android6Looper7RequestEEENS_22__unordered_map_hasherImS5_NS_4hashImEELb1EEENS_21__unordered_map_equalImS5_NS_8equal_toImEELb1EEENS_9allocatorIS5_EEE14__erase_uniqueImEEmRKT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeImN7android6Looper7RequestEEENS_22__unordered_map_hasherImS5_NS_4hashImEELb1EEENS_21__unordered_map_equalImS5_NS_8equal_toImEELb1EEENS_9allocatorIS5_EEE25__emplace_unique_key_argsImJRKmRS4_EEENS_4pairINS_15__hash_iteratorIPNS_11__hash_nodeIS5_PvEEEEbEERKT_DpOT0_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeImN7android6Looper7RequestEEENS_22__unordered_map_hasherImS5_NS_4hashImEELb1EEENS_21__unordered_map_equalImS5_NS_8equal_toImEELb1EEENS_9allocatorIS5_EEE6rehashEm"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeImN7android6Looper7RequestEEENS_22__unordered_map_hasherImS5_NS_4hashImEELb1EEENS_21__unordered_map_equalImS5_NS_8equal_toImEELb1EEENS_9allocatorIS5_EEE6removeENS_21__hash_const_iteratorIPNS_11__hash_nodeIS5_PvEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeImN7android6Looper7RequestEEENS_22__unordered_map_hasherImS5_NS_4hashImEELb1EEENS_21__unordered_map_equalImS5_NS_8equal_toImEELb1EEENS_9allocatorIS5_EEE8__rehashEm"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android14LooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android14LooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android14MessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android14MessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android6ThreadD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n24_N7android6ThreadD1Ev"
+ },
+ {
+ "name" : "androidCreateRawThreadEtc"
+ },
+ {
+ "name" : "androidCreateThread"
+ },
+ {
+ "name" : "androidCreateThreadEtc"
+ },
+ {
+ "name" : "androidGetThreadId"
+ },
+ {
+ "name" : "androidGetThreadPriority"
+ },
+ {
+ "name" : "androidSetCreateThreadFunc"
+ },
+ {
+ "name" : "androidSetThreadName"
+ },
+ {
+ "name" : "androidSetThreadPriority"
+ },
+ {
+ "name" : "do_report_sysprop_change"
+ },
+ {
+ "name" : "strcmp16"
+ },
+ {
+ "name" : "strlen16"
+ },
+ {
+ "name" : "strncmp16"
+ },
+ {
+ "name" : "strnlen16"
+ },
+ {
+ "name" : "strstr16"
+ },
+ {
+ "name" : "strzcmp16"
+ },
+ {
+ "name" : "systemTime"
+ },
+ {
+ "name" : "toMillisecondTimeoutDelay"
+ },
+ {
+ "name" : "utf16_to_utf8"
+ },
+ {
+ "name" : "utf16_to_utf8_length"
+ },
+ {
+ "name" : "utf32_from_utf8_at"
+ },
+ {
+ "name" : "utf32_to_utf8"
+ },
+ {
+ "name" : "utf32_to_utf8_length"
+ },
+ {
+ "name" : "utf8_to_utf16"
+ },
+ {
+ "name" : "utf8_to_utf16_length"
+ },
+ {
+ "name" : "utf8_to_utf16_no_null_terminator"
+ }
+ ],
+ "elf_objects" :
+ [
+ {
+ "name" : "_ZN7android7FileMap9mPageSizeE"
+ },
+ {
+ "name" : "_ZTCN7android18WeakMessageHandlerE0_NS_14MessageHandlerE"
+ },
+ {
+ "name" : "_ZTCN7android20SimpleLooperCallbackE0_NS_14LooperCallbackE"
+ },
+ {
+ "name" : "_ZTTN7android14LooperCallbackE"
+ },
+ {
+ "name" : "_ZTTN7android14MessageHandlerE"
+ },
+ {
+ "name" : "_ZTTN7android18WeakMessageHandlerE"
+ },
+ {
+ "name" : "_ZTTN7android20SimpleLooperCallbackE"
+ },
+ {
+ "name" : "_ZTTN7android6ThreadE"
+ },
+ {
+ "name" : "_ZTVN7android10LogPrinterE"
+ },
+ {
+ "name" : "_ZTVN7android10VectorImplE"
+ },
+ {
+ "name" : "_ZTVN7android13PrefixPrinterE"
+ },
+ {
+ "name" : "_ZTVN7android14LooperCallbackE"
+ },
+ {
+ "name" : "_ZTVN7android14MessageHandlerE"
+ },
+ {
+ "name" : "_ZTVN7android14String8PrinterE"
+ },
+ {
+ "name" : "_ZTVN7android16SortedVectorImplE"
+ },
+ {
+ "name" : "_ZTVN7android18WeakMessageHandlerE"
+ },
+ {
+ "name" : "_ZTVN7android20SimpleLooperCallbackE"
+ },
+ {
+ "name" : "_ZTVN7android6LooperE"
+ },
+ {
+ "name" : "_ZTVN7android6ThreadE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "name" : "_ZTVN7android7PrinterE"
+ },
+ {
+ "name" : "_ZTVN7android7RefBaseE"
+ },
+ {
+ "name" : "_ZTVN7android9FdPrinterE"
+ }
+ ],
+ "enum_types" :
+ [
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : -1,
+ "name" : "SP_DEFAULT"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "SP_BACKGROUND"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "SP_FOREGROUND"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "SP_SYSTEM"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "SP_AUDIO_APP"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "SP_AUDIO_SYS"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "SP_TOP_APP"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "SP_RT_APP"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "SP_RESTRICTED"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "SP_CNT"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "SP_MAX"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "SP_SYSTEM_DEFAULT"
+ }
+ ],
+ "linker_set_key" : "_ZTI11SchedPolicy",
+ "name" : "SchedPolicy",
+ "referenced_type" : "_ZTI11SchedPolicy",
+ "self_type" : "_ZTI11SchedPolicy",
+ "size" : 4,
+ "source_file" : "system/core/libprocessgroup/include/processgroup/sched_policy.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_HDR_DOLBY_VISION"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_HDR_HDR10"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_HDR_HLG"
+ }
+ ],
+ "linker_set_key" : "_ZTI13android_hdr_t",
+ "name" : "android_hdr_t",
+ "referenced_type" : "_ZTI13android_hdr_t",
+ "self_type" : "_ZTI13android_hdr_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_HDR_HDR10_PLUS"
+ }
+ ],
+ "linker_set_key" : "_ZTI18android_hdr_v1_2_t",
+ "name" : "android_hdr_v1_2_t",
+ "referenced_type" : "_ZTI18android_hdr_v1_2_t",
+ "self_type" : "_ZTI18android_hdr_v1_2_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.2.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "ANDROID_LOG_UNKNOWN"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "ANDROID_LOG_DEFAULT"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "ANDROID_LOG_VERBOSE"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "ANDROID_LOG_DEBUG"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "ANDROID_LOG_INFO"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "ANDROID_LOG_WARN"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "ANDROID_LOG_ERROR"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "ANDROID_LOG_FATAL"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "ANDROID_LOG_SILENT"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_LogPriority",
+ "name" : "android_LogPriority",
+ "referenced_type" : "_ZTI19android_LogPriority",
+ "self_type" : "_ZTI19android_LogPriority",
+ "size" : 4,
+ "source_file" : "system/logging/liblog/include_vndk/android/log.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_UNKNOWN"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_DATASPACE_ARBITRARY"
+ },
+ {
+ "enum_field_value" : 16,
+ "name" : "HAL_DATASPACE_STANDARD_SHIFT"
+ },
+ {
+ "enum_field_value" : 4128768,
+ "name" : "HAL_DATASPACE_STANDARD_MASK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_STANDARD_UNSPECIFIED"
+ },
+ {
+ "enum_field_value" : 65536,
+ "name" : "HAL_DATASPACE_STANDARD_BT709"
+ },
+ {
+ "enum_field_value" : 131072,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_625"
+ },
+ {
+ "enum_field_value" : 196608,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 262144,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_525"
+ },
+ {
+ "enum_field_value" : 327680,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 393216,
+ "name" : "HAL_DATASPACE_STANDARD_BT2020"
+ },
+ {
+ "enum_field_value" : 458752,
+ "name" : "HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE"
+ },
+ {
+ "enum_field_value" : 524288,
+ "name" : "HAL_DATASPACE_STANDARD_BT470M"
+ },
+ {
+ "enum_field_value" : 589824,
+ "name" : "HAL_DATASPACE_STANDARD_FILM"
+ },
+ {
+ "enum_field_value" : 655360,
+ "name" : "HAL_DATASPACE_STANDARD_DCI_P3"
+ },
+ {
+ "enum_field_value" : 720896,
+ "name" : "HAL_DATASPACE_STANDARD_ADOBE_RGB"
+ },
+ {
+ "enum_field_value" : 22,
+ "name" : "HAL_DATASPACE_TRANSFER_SHIFT"
+ },
+ {
+ "enum_field_value" : 130023424,
+ "name" : "HAL_DATASPACE_TRANSFER_MASK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_TRANSFER_UNSPECIFIED"
+ },
+ {
+ "enum_field_value" : 4194304,
+ "name" : "HAL_DATASPACE_TRANSFER_LINEAR"
+ },
+ {
+ "enum_field_value" : 8388608,
+ "name" : "HAL_DATASPACE_TRANSFER_SRGB"
+ },
+ {
+ "enum_field_value" : 12582912,
+ "name" : "HAL_DATASPACE_TRANSFER_SMPTE_170M"
+ },
+ {
+ "enum_field_value" : 16777216,
+ "name" : "HAL_DATASPACE_TRANSFER_GAMMA2_2"
+ },
+ {
+ "enum_field_value" : 20971520,
+ "name" : "HAL_DATASPACE_TRANSFER_GAMMA2_6"
+ },
+ {
+ "enum_field_value" : 25165824,
+ "name" : "HAL_DATASPACE_TRANSFER_GAMMA2_8"
+ },
+ {
+ "enum_field_value" : 29360128,
+ "name" : "HAL_DATASPACE_TRANSFER_ST2084"
+ },
+ {
+ "enum_field_value" : 33554432,
+ "name" : "HAL_DATASPACE_TRANSFER_HLG"
+ },
+ {
+ "enum_field_value" : 27,
+ "name" : "HAL_DATASPACE_RANGE_SHIFT"
+ },
+ {
+ "enum_field_value" : 939524096,
+ "name" : "HAL_DATASPACE_RANGE_MASK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_RANGE_UNSPECIFIED"
+ },
+ {
+ "enum_field_value" : 134217728,
+ "name" : "HAL_DATASPACE_RANGE_FULL"
+ },
+ {
+ "enum_field_value" : 268435456,
+ "name" : "HAL_DATASPACE_RANGE_LIMITED"
+ },
+ {
+ "enum_field_value" : 402653184,
+ "name" : "HAL_DATASPACE_RANGE_EXTENDED"
+ },
+ {
+ "enum_field_value" : 512,
+ "name" : "HAL_DATASPACE_SRGB_LINEAR"
+ },
+ {
+ "enum_field_value" : 138477568,
+ "name" : "HAL_DATASPACE_V0_SRGB_LINEAR"
+ },
+ {
+ "enum_field_value" : 406913024,
+ "name" : "HAL_DATASPACE_V0_SCRGB_LINEAR"
+ },
+ {
+ "enum_field_value" : 513,
+ "name" : "HAL_DATASPACE_SRGB"
+ },
+ {
+ "enum_field_value" : 142671872,
+ "name" : "HAL_DATASPACE_V0_SRGB"
+ },
+ {
+ "enum_field_value" : 411107328,
+ "name" : "HAL_DATASPACE_V0_SCRGB"
+ },
+ {
+ "enum_field_value" : 257,
+ "name" : "HAL_DATASPACE_JFIF"
+ },
+ {
+ "enum_field_value" : 146931712,
+ "name" : "HAL_DATASPACE_V0_JFIF"
+ },
+ {
+ "enum_field_value" : 258,
+ "name" : "HAL_DATASPACE_BT601_625"
+ },
+ {
+ "enum_field_value" : 281149440,
+ "name" : "HAL_DATASPACE_V0_BT601_625"
+ },
+ {
+ "enum_field_value" : 259,
+ "name" : "HAL_DATASPACE_BT601_525"
+ },
+ {
+ "enum_field_value" : 281280512,
+ "name" : "HAL_DATASPACE_V0_BT601_525"
+ },
+ {
+ "enum_field_value" : 260,
+ "name" : "HAL_DATASPACE_BT709"
+ },
+ {
+ "enum_field_value" : 281083904,
+ "name" : "HAL_DATASPACE_V0_BT709"
+ },
+ {
+ "enum_field_value" : 139067392,
+ "name" : "HAL_DATASPACE_DCI_P3_LINEAR"
+ },
+ {
+ "enum_field_value" : 155844608,
+ "name" : "HAL_DATASPACE_DCI_P3"
+ },
+ {
+ "enum_field_value" : 139067392,
+ "name" : "HAL_DATASPACE_DISPLAY_P3_LINEAR"
+ },
+ {
+ "enum_field_value" : 143261696,
+ "name" : "HAL_DATASPACE_DISPLAY_P3"
+ },
+ {
+ "enum_field_value" : 151715840,
+ "name" : "HAL_DATASPACE_ADOBE_RGB"
+ },
+ {
+ "enum_field_value" : 138805248,
+ "name" : "HAL_DATASPACE_BT2020_LINEAR"
+ },
+ {
+ "enum_field_value" : 147193856,
+ "name" : "HAL_DATASPACE_BT2020"
+ },
+ {
+ "enum_field_value" : 163971072,
+ "name" : "HAL_DATASPACE_BT2020_PQ"
+ },
+ {
+ "enum_field_value" : 4096,
+ "name" : "HAL_DATASPACE_DEPTH"
+ },
+ {
+ "enum_field_value" : 4097,
+ "name" : "HAL_DATASPACE_SENSOR"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_dataspace_t",
+ "name" : "android_dataspace_t",
+ "referenced_type" : "_ZTI19android_dataspace_t",
+ "self_type" : "_ZTI19android_dataspace_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "FLEX_FORMAT_INVALID"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "FLEX_FORMAT_Y"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "FLEX_FORMAT_YCbCr"
+ },
+ {
+ "enum_field_value" : 1073741831,
+ "name" : "FLEX_FORMAT_YCbCrA"
+ },
+ {
+ "enum_field_value" : 7168,
+ "name" : "FLEX_FORMAT_RGB"
+ },
+ {
+ "enum_field_value" : 1073748992,
+ "name" : "FLEX_FORMAT_RGBA"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_flex_format",
+ "name" : "android_flex_format",
+ "referenced_type" : "_ZTI19android_flex_format",
+ "self_type" : "_ZTI19android_flex_format",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_TRANSFORM_FLIP_H"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_TRANSFORM_FLIP_V"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_TRANSFORM_ROT_90"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_TRANSFORM_ROT_180"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "HAL_TRANSFORM_ROT_270"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_transform_t",
+ "name" : "android_transform_t",
+ "referenced_type" : "_ZTI19android_transform_t",
+ "self_type" : "_ZTI19android_transform_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_COLOR_MODE_NATIVE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_625"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_525"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT709"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "HAL_COLOR_MODE_DCI_P3"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "HAL_COLOR_MODE_SRGB"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "HAL_COLOR_MODE_ADOBE_RGB"
+ },
+ {
+ "enum_field_value" : 9,
+ "name" : "HAL_COLOR_MODE_DISPLAY_P3"
+ }
+ ],
+ "linker_set_key" : "_ZTI20android_color_mode_t",
+ "name" : "android_color_mode_t",
+ "referenced_type" : "_ZTI20android_color_mode_t",
+ "self_type" : "_ZTI20android_color_mode_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "SYSTEM_TIME_REALTIME"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "SYSTEM_TIME_MONOTONIC"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "SYSTEM_TIME_PROCESS"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "SYSTEM_TIME_THREAD"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "SYSTEM_TIME_BOOTTIME"
+ }
+ ],
+ "linker_set_key" : "_ZTI21$SYSTEM_TIME_BOOTTIME",
+ "name" : "(unnamed)",
+ "referenced_type" : "_ZTI21$SYSTEM_TIME_BOOTTIME",
+ "self_type" : "_ZTI21$SYSTEM_TIME_BOOTTIME",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Timers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "FLEX_COMPONENT_Y"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "FLEX_COMPONENT_Cb"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "FLEX_COMPONENT_Cr"
+ },
+ {
+ "enum_field_value" : 1024,
+ "name" : "FLEX_COMPONENT_R"
+ },
+ {
+ "enum_field_value" : 2048,
+ "name" : "FLEX_COMPONENT_G"
+ },
+ {
+ "enum_field_value" : 4096,
+ "name" : "FLEX_COMPONENT_B"
+ },
+ {
+ "enum_field_value" : 1073741824,
+ "name" : "FLEX_COMPONENT_A"
+ }
+ ],
+ "linker_set_key" : "_ZTI22android_flex_component",
+ "name" : "android_flex_component",
+ "referenced_type" : "_ZTI22android_flex_component",
+ "self_type" : "_ZTI22android_flex_component",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_PIXEL_FORMAT_RGBA_8888"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_PIXEL_FORMAT_RGBX_8888"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_PIXEL_FORMAT_RGB_888"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_PIXEL_FORMAT_RGB_565"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "HAL_PIXEL_FORMAT_BGRA_8888"
+ },
+ {
+ "enum_field_value" : 16,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_422_SP"
+ },
+ {
+ "enum_field_value" : 17,
+ "name" : "HAL_PIXEL_FORMAT_YCRCB_420_SP"
+ },
+ {
+ "enum_field_value" : 20,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_422_I"
+ },
+ {
+ "enum_field_value" : 22,
+ "name" : "HAL_PIXEL_FORMAT_RGBA_FP16"
+ },
+ {
+ "enum_field_value" : 32,
+ "name" : "HAL_PIXEL_FORMAT_RAW16"
+ },
+ {
+ "enum_field_value" : 33,
+ "name" : "HAL_PIXEL_FORMAT_BLOB"
+ },
+ {
+ "enum_field_value" : 34,
+ "name" : "HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED"
+ },
+ {
+ "enum_field_value" : 35,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_420_888"
+ },
+ {
+ "enum_field_value" : 36,
+ "name" : "HAL_PIXEL_FORMAT_RAW_OPAQUE"
+ },
+ {
+ "enum_field_value" : 37,
+ "name" : "HAL_PIXEL_FORMAT_RAW10"
+ },
+ {
+ "enum_field_value" : 38,
+ "name" : "HAL_PIXEL_FORMAT_RAW12"
+ },
+ {
+ "enum_field_value" : 43,
+ "name" : "HAL_PIXEL_FORMAT_RGBA_1010102"
+ },
+ {
+ "enum_field_value" : 538982489,
+ "name" : "HAL_PIXEL_FORMAT_Y8"
+ },
+ {
+ "enum_field_value" : 540422489,
+ "name" : "HAL_PIXEL_FORMAT_Y16"
+ },
+ {
+ "enum_field_value" : 842094169,
+ "name" : "HAL_PIXEL_FORMAT_YV12"
+ }
+ ],
+ "linker_set_key" : "_ZTI22android_pixel_format_t",
+ "name" : "android_pixel_format_t",
+ "referenced_type" : "_ZTI22android_pixel_format_t",
+ "self_type" : "_ZTI22android_pixel_format_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 19,
+ "name" : "ANDROID_PRIORITY_LOWEST"
+ },
+ {
+ "enum_field_value" : 10,
+ "name" : "ANDROID_PRIORITY_BACKGROUND"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "ANDROID_PRIORITY_NORMAL"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "ANDROID_PRIORITY_FOREGROUND"
+ },
+ {
+ "enum_field_value" : -4,
+ "name" : "ANDROID_PRIORITY_DISPLAY"
+ },
+ {
+ "enum_field_value" : -8,
+ "name" : "ANDROID_PRIORITY_URGENT_DISPLAY"
+ },
+ {
+ "enum_field_value" : -10,
+ "name" : "ANDROID_PRIORITY_VIDEO"
+ },
+ {
+ "enum_field_value" : -16,
+ "name" : "ANDROID_PRIORITY_AUDIO"
+ },
+ {
+ "enum_field_value" : -19,
+ "name" : "ANDROID_PRIORITY_URGENT_AUDIO"
+ },
+ {
+ "enum_field_value" : -20,
+ "name" : "ANDROID_PRIORITY_HIGHEST"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "ANDROID_PRIORITY_DEFAULT"
+ },
+ {
+ "enum_field_value" : -1,
+ "name" : "ANDROID_PRIORITY_MORE_FAVORABLE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "ANDROID_PRIORITY_LESS_FAVORABLE"
+ }
+ ],
+ "linker_set_key" : "_ZTI23$ANDROID_PRIORITY_AUDIO",
+ "name" : "(unnamed)",
+ "referenced_type" : "_ZTI23$ANDROID_PRIORITY_AUDIO",
+ "self_type" : "_ZTI23$ANDROID_PRIORITY_AUDIO",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/thread_defs.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 281411584,
+ "name" : "HAL_DATASPACE_BT2020_ITU"
+ },
+ {
+ "enum_field_value" : 298188800,
+ "name" : "HAL_DATASPACE_BT2020_ITU_PQ"
+ },
+ {
+ "enum_field_value" : 302383104,
+ "name" : "HAL_DATASPACE_BT2020_ITU_HLG"
+ },
+ {
+ "enum_field_value" : 168165376,
+ "name" : "HAL_DATASPACE_BT2020_HLG"
+ }
+ ],
+ "linker_set_key" : "_ZTI24android_dataspace_v1_1_t",
+ "name" : "android_dataspace_v1_1_t",
+ "referenced_type" : "_ZTI24android_dataspace_v1_1_t",
+ "self_type" : "_ZTI24android_dataspace_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 142999552,
+ "name" : "HAL_DATASPACE_DISPLAY_BT2020"
+ },
+ {
+ "enum_field_value" : 4098,
+ "name" : "HAL_DATASPACE_DYNAMIC_DEPTH"
+ },
+ {
+ "enum_field_value" : 4099,
+ "name" : "HAL_DATASPACE_JPEG_APP_SEGMENTS"
+ },
+ {
+ "enum_field_value" : 4100,
+ "name" : "HAL_DATASPACE_HEIF"
+ }
+ ],
+ "linker_set_key" : "_ZTI24android_dataspace_v1_2_t",
+ "name" : "android_dataspace_v1_2_t",
+ "referenced_type" : "_ZTI24android_dataspace_v1_2_t",
+ "self_type" : "_ZTI24android_dataspace_v1_2_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.2.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 10,
+ "name" : "HAL_COLOR_MODE_BT2020"
+ },
+ {
+ "enum_field_value" : 11,
+ "name" : "HAL_COLOR_MODE_BT2100_PQ"
+ },
+ {
+ "enum_field_value" : 12,
+ "name" : "HAL_COLOR_MODE_BT2100_HLG"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_color_mode_v1_1_t",
+ "name" : "android_color_mode_v1_1_t",
+ "referenced_type" : "_ZTI25android_color_mode_v1_1_t",
+ "self_type" : "_ZTI25android_color_mode_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_COLOR_TRANSFORM_IDENTITY"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_COLOR_TRANSFORM_VALUE_INVERSE"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_COLOR_TRANSFORM_GRAYSCALE"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_color_transform_t",
+ "name" : "android_color_transform_t",
+ "referenced_type" : "_ZTI25android_color_transform_t",
+ "self_type" : "_ZTI25android_color_transform_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 39,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_422_888"
+ },
+ {
+ "enum_field_value" : 40,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_444_888"
+ },
+ {
+ "enum_field_value" : 41,
+ "name" : "HAL_PIXEL_FORMAT_FLEX_RGB_888"
+ },
+ {
+ "enum_field_value" : 42,
+ "name" : "HAL_PIXEL_FORMAT_FLEX_RGBA_8888"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_pixel_format_sw_t",
+ "name" : "android_pixel_format_sw_t",
+ "referenced_type" : "_ZTI25android_pixel_format_sw_t",
+ "self_type" : "_ZTI25android_pixel_format_sw_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-sw.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 48,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_16"
+ },
+ {
+ "enum_field_value" : 49,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_24"
+ },
+ {
+ "enum_field_value" : 50,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8"
+ },
+ {
+ "enum_field_value" : 51,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_32F"
+ },
+ {
+ "enum_field_value" : 52,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8"
+ },
+ {
+ "enum_field_value" : 53,
+ "name" : "HAL_PIXEL_FORMAT_STENCIL_8"
+ },
+ {
+ "enum_field_value" : 54,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_P010"
+ }
+ ],
+ "linker_set_key" : "_ZTI27android_pixel_format_v1_1_t",
+ "name" : "android_pixel_format_v1_1_t",
+ "referenced_type" : "_ZTI27android_pixel_format_v1_1_t",
+ "self_type" : "_ZTI27android_pixel_format_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 55,
+ "name" : "HAL_PIXEL_FORMAT_HSV_888"
+ }
+ ],
+ "linker_set_key" : "_ZTI27android_pixel_format_v1_2_t",
+ "name" : "android_pixel_format_v1_2_t",
+ "referenced_type" : "_ZTI27android_pixel_format_v1_2_t",
+ "self_type" : "_ZTI27android_pixel_format_v1_2_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.2.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_RENDER_INTENT_COLORIMETRIC"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_RENDER_INTENT_ENHANCE"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_RENDER_INTENT_TONE_MAP_COLORIMETRIC"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_RENDER_INTENT_TONE_MAP_ENHANCE"
+ }
+ ],
+ "linker_set_key" : "_ZTI28android_render_intent_v1_1_t",
+ "name" : "android_render_intent_v1_1_t",
+ "referenced_type" : "_ZTI28android_render_intent_v1_1_t",
+ "self_type" : "_ZTI28android_render_intent_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "LOG_ID_MIN"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "LOG_ID_MAIN"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "LOG_ID_RADIO"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "LOG_ID_EVENTS"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "LOG_ID_SYSTEM"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "LOG_ID_CRASH"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "LOG_ID_STATS"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "LOG_ID_SECURITY"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "LOG_ID_KERNEL"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "LOG_ID_MAX"
+ },
+ {
+ "enum_field_value" : 2147483647,
+ "name" : "LOG_ID_DEFAULT"
+ }
+ ],
+ "linker_set_key" : "_ZTI6log_id",
+ "name" : "log_id",
+ "referenced_type" : "_ZTI6log_id",
+ "self_type" : "_ZTI6log_id",
+ "size" : 4,
+ "source_file" : "system/logging/liblog/include_vndk/android/log.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::VectorImpl::HAS_TRIVIAL_CTOR"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "android::VectorImpl::HAS_TRIVIAL_DTOR"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "android::VectorImpl::HAS_TRIVIAL_COPY"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android10VectorImpl17$HAS_TRIVIAL_COPYE",
+ "name" : "android::VectorImpl::(unnamed)",
+ "referenced_type" : "_ZTIN7android10VectorImpl17$HAS_TRIVIAL_COPYE",
+ "self_type" : "_ZTIN7android10VectorImpl17$HAS_TRIVIAL_COPYE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_pointer<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_pointer<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_pointer<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_pointer<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_pointer<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_pointer<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::OK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::NO_ERROR"
+ },
+ {
+ "enum_field_value" : -2147483648,
+ "name" : "android::UNKNOWN_ERROR"
+ },
+ {
+ "enum_field_value" : -12,
+ "name" : "android::NO_MEMORY"
+ },
+ {
+ "enum_field_value" : -38,
+ "name" : "android::INVALID_OPERATION"
+ },
+ {
+ "enum_field_value" : -22,
+ "name" : "android::BAD_VALUE"
+ },
+ {
+ "enum_field_value" : -2147483647,
+ "name" : "android::BAD_TYPE"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "android::NAME_NOT_FOUND"
+ },
+ {
+ "enum_field_value" : -1,
+ "name" : "android::PERMISSION_DENIED"
+ },
+ {
+ "enum_field_value" : -19,
+ "name" : "android::NO_INIT"
+ },
+ {
+ "enum_field_value" : -17,
+ "name" : "android::ALREADY_EXISTS"
+ },
+ {
+ "enum_field_value" : -32,
+ "name" : "android::DEAD_OBJECT"
+ },
+ {
+ "enum_field_value" : -2147483646,
+ "name" : "android::FAILED_TRANSACTION"
+ },
+ {
+ "enum_field_value" : -75,
+ "name" : "android::BAD_INDEX"
+ },
+ {
+ "enum_field_value" : -61,
+ "name" : "android::NOT_ENOUGH_DATA"
+ },
+ {
+ "enum_field_value" : -11,
+ "name" : "android::WOULD_BLOCK"
+ },
+ {
+ "enum_field_value" : -110,
+ "name" : "android::TIMED_OUT"
+ },
+ {
+ "enum_field_value" : -74,
+ "name" : "android::UNKNOWN_TRANSACTION"
+ },
+ {
+ "enum_field_value" : -2147483641,
+ "name" : "android::FDS_NOT_ALLOWED"
+ },
+ {
+ "enum_field_value" : -2147483640,
+ "name" : "android::UNEXPECTED_NULL"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android15$ALREADY_EXISTSE",
+ "name" : "android::(unnamed)",
+ "referenced_type" : "_ZTIN7android15$ALREADY_EXISTSE",
+ "self_type" : "_ZTIN7android15$ALREADY_EXISTSE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Errors.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 19,
+ "name" : "android::PRIORITY_LOWEST"
+ },
+ {
+ "enum_field_value" : 10,
+ "name" : "android::PRIORITY_BACKGROUND"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::PRIORITY_NORMAL"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "android::PRIORITY_FOREGROUND"
+ },
+ {
+ "enum_field_value" : -4,
+ "name" : "android::PRIORITY_DISPLAY"
+ },
+ {
+ "enum_field_value" : -8,
+ "name" : "android::PRIORITY_URGENT_DISPLAY"
+ },
+ {
+ "enum_field_value" : -16,
+ "name" : "android::PRIORITY_AUDIO"
+ },
+ {
+ "enum_field_value" : -19,
+ "name" : "android::PRIORITY_URGENT_AUDIO"
+ },
+ {
+ "enum_field_value" : -20,
+ "name" : "android::PRIORITY_HIGHEST"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::PRIORITY_DEFAULT"
+ },
+ {
+ "enum_field_value" : -1,
+ "name" : "android::PRIORITY_MORE_FAVORABLE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::PRIORITY_LESS_FAVORABLE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android15$PRIORITY_AUDIOE",
+ "name" : "android::(unnamed)",
+ "referenced_type" : "_ZTIN7android15$PRIORITY_AUDIOE",
+ "self_type" : "_ZTIN7android15$PRIORITY_AUDIOE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/ThreadDefs.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_copy<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_copy<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_copy<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_copy<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_copy<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_copy<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIbE6$valueE",
+ "name" : "android::trait_trivial_copy<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIcE6$valueE",
+ "name" : "android::trait_trivial_copy<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIdE6$valueE",
+ "name" : "android::trait_trivial_copy<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIfE6$valueE",
+ "name" : "android::trait_trivial_copy<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIhE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIiE6$valueE",
+ "name" : "android::trait_trivial_copy<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIjE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIlE6$valueE",
+ "name" : "android::trait_trivial_copy<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyImE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIsE6$valueE",
+ "name" : "android::trait_trivial_copy<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyItE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIvE6$valueE",
+ "name" : "android::trait_trivial_copy<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIxE6$valueE",
+ "name" : "android::trait_trivial_copy<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIyE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_ctor<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_ctor<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_ctor<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_ctor<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_ctor<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_ctor<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIbE6$valueE",
+ "name" : "android::trait_trivial_ctor<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIcE6$valueE",
+ "name" : "android::trait_trivial_ctor<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIdE6$valueE",
+ "name" : "android::trait_trivial_ctor<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIfE6$valueE",
+ "name" : "android::trait_trivial_ctor<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIhE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIiE6$valueE",
+ "name" : "android::trait_trivial_ctor<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIjE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIlE6$valueE",
+ "name" : "android::trait_trivial_ctor<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorImE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIsE6$valueE",
+ "name" : "android::trait_trivial_ctor<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorItE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIvE6$valueE",
+ "name" : "android::trait_trivial_ctor<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIxE6$valueE",
+ "name" : "android::trait_trivial_ctor<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIyE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_dtor<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_dtor<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_dtor<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_dtor<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_dtor<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_dtor<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIbE6$valueE",
+ "name" : "android::trait_trivial_dtor<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIcE6$valueE",
+ "name" : "android::trait_trivial_dtor<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIdE6$valueE",
+ "name" : "android::trait_trivial_dtor<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIfE6$valueE",
+ "name" : "android::trait_trivial_dtor<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIhE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIiE6$valueE",
+ "name" : "android::trait_trivial_dtor<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIjE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIlE6$valueE",
+ "name" : "android::trait_trivial_dtor<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorImE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIsE6$valueE",
+ "name" : "android::trait_trivial_dtor<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorItE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIvE6$valueE",
+ "name" : "android::trait_trivial_dtor<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIxE6$valueE",
+ "name" : "android::trait_trivial_dtor<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIyE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_move<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_move<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_move<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_move<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_move<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_move<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<android::String8>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_7String8EE6$valueE",
+ "name" : "android::trait_trivial_move<android::String8>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<android::String16>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_8String16EE6$valueE",
+ "name" : "android::trait_trivial_move<android::String16>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIbE6$valueE",
+ "name" : "android::trait_trivial_move<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIcE6$valueE",
+ "name" : "android::trait_trivial_move<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIdE6$valueE",
+ "name" : "android::trait_trivial_move<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIfE6$valueE",
+ "name" : "android::trait_trivial_move<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIhE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIiE6$valueE",
+ "name" : "android::trait_trivial_move<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIjE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIlE6$valueE",
+ "name" : "android::trait_trivial_move<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveImE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIsE6$valueE",
+ "name" : "android::trait_trivial_move<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveItE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIvE6$valueE",
+ "name" : "android::trait_trivial_move<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIxE6$valueE",
+ "name" : "android::trait_trivial_move<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIyE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::Mutex::PRIVATE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Mutex::SHARED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android5Mutex8$PRIVATEE",
+ "name" : "android::Mutex::(unnamed)",
+ "referenced_type" : "_ZTIN7android5Mutex8$PRIVATEE",
+ "self_type" : "_ZTIN7android5Mutex8$PRIVATEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Looper::EVENT_INPUT"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "android::Looper::EVENT_OUTPUT"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "android::Looper::EVENT_ERROR"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "android::Looper::EVENT_HANGUP"
+ },
+ {
+ "enum_field_value" : 16,
+ "name" : "android::Looper::EVENT_INVALID"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper12$EVENT_ERRORE",
+ "name" : "android::Looper::(unnamed)",
+ "referenced_type" : "_ZTIN7android6Looper12$EVENT_ERRORE",
+ "self_type" : "_ZTIN7android6Looper12$EVENT_ERRORE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : -1,
+ "name" : "android::Looper::POLL_WAKE"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "android::Looper::POLL_CALLBACK"
+ },
+ {
+ "enum_field_value" : -3,
+ "name" : "android::Looper::POLL_TIMEOUT"
+ },
+ {
+ "enum_field_value" : -4,
+ "name" : "android::Looper::POLL_ERROR"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper14$POLL_CALLBACKE",
+ "name" : "android::Looper::(unnamed)",
+ "referenced_type" : "_ZTIN7android6Looper14$POLL_CALLBACKE",
+ "self_type" : "_ZTIN7android6Looper14$POLL_CALLBACKE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Looper::PREPARE_ALLOW_NON_CALLBACKS"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper28$PREPARE_ALLOW_NON_CALLBACKSE",
+ "name" : "android::Looper::(unnamed)",
+ "referenced_type" : "_ZTIN7android6Looper28$PREPARE_ALLOW_NON_CALLBACKSE",
+ "self_type" : "_ZTIN7android6Looper28$PREPARE_ALLOW_NON_CALLBACKSE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::RWLock::PRIVATE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RWLock::SHARED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLock8$PRIVATEE",
+ "name" : "android::RWLock::(unnamed)",
+ "referenced_type" : "_ZTIN7android6RWLock8$PRIVATEE",
+ "self_type" : "_ZTIN7android6RWLock8$PRIVATEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::is_pointer"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_ctor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_dtor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_copy"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_move"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEE17$has_trivial_copyE",
+ "name" : "android::traits<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEE17$has_trivial_copyE",
+ "self_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEE17$has_trivial_copyE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::is_pointer"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_ctor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_dtor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_copy"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_move"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEE17$has_trivial_copyE",
+ "name" : "android::traits<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEE17$has_trivial_copyE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEE17$has_trivial_copyE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::is_pointer"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_ctor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_dtor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_copy"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_move"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper8ResponseEE17$has_trivial_copyE",
+ "name" : "android::traits<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEE17$has_trivial_copyE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEE17$has_trivial_copyE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::FileMap::NORMAL"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::FileMap::RANDOM"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "android::FileMap::SEQUENTIAL"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "android::FileMap::WILLNEED"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "android::FileMap::DONTNEED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7FileMap9MapAdviceE",
+ "name" : "android::FileMap::MapAdvice",
+ "referenced_type" : "_ZTIN7android7FileMap9MapAdviceE",
+ "self_type" : "_ZTIN7android7FileMap9MapAdviceE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "access" : "protected",
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RefBase::FIRST_INC_STRONG"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7RefBase17$FIRST_INC_STRONGE",
+ "name" : "android::RefBase::(unnamed)",
+ "referenced_type" : "_ZTIN7android7RefBase17$FIRST_INC_STRONGE",
+ "self_type" : "_ZTIN7android7RefBase17$FIRST_INC_STRONGE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "access" : "protected",
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::RefBase::OBJECT_LIFETIME_STRONG"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RefBase::OBJECT_LIFETIME_WEAK"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RefBase::OBJECT_LIFETIME_MASK"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7RefBase21$OBJECT_LIFETIME_MASKE",
+ "name" : "android::RefBase::(unnamed)",
+ "referenced_type" : "_ZTIN7android7RefBase21$OBJECT_LIFETIME_MASKE",
+ "self_type" : "_ZTIN7android7RefBase21$OBJECT_LIFETIME_MASKE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::Condition::WAKE_UP_ONE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Condition::WAKE_UP_ALL"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9Condition10WakeUpTypeE",
+ "name" : "android::Condition::WakeUpType",
+ "referenced_type" : "_ZTIN7android9Condition10WakeUpTypeE",
+ "self_type" : "_ZTIN7android9Condition10WakeUpTypeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Condition.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::Condition::PRIVATE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Condition::SHARED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9Condition8$PRIVATEE",
+ "name" : "android::Condition::(unnamed)",
+ "referenced_type" : "_ZTIN7android9Condition8$PRIVATEE",
+ "self_type" : "_ZTIN7android9Condition8$PRIVATEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Condition.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 20,
+ "name" : "android::FdPrinter::MAX_FORMAT_STRING"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9FdPrinter18$MAX_FORMAT_STRINGE",
+ "name" : "android::FdPrinter::(unnamed)",
+ "referenced_type" : "_ZTIN7android9FdPrinter18$MAX_FORMAT_STRINGE",
+ "self_type" : "_ZTIN7android9FdPrinter18$MAX_FORMAT_STRINGE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "underlying_type" : "_ZTIj"
+ }
+ ],
+ "function_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPFiPvES_PKcimPS_E",
+ "name" : "int (int (*)(void *), void *, const char *, int, unsigned long, void **)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPFiPvES_PKcimPS_E",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPFiPvES_PKcimPS_E",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPKvS0_E",
+ "name" : "int (const void *, const void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPKvS0_E",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPKvS0_E",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPKvS0_PvE",
+ "name" : "int (const void *, const void *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPKvS0_PvE",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPKvS0_PvE",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.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/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiiiPvE",
+ "name" : "int (int, int, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiiiPvE",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiiiPvE",
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFvvE",
+ "name" : "void ()",
+ "referenced_type" : "_ZTIFvvE",
+ "return_type" : "_ZTIv",
+ "self_type" : "_ZTIFvvE",
+ "source_file" : "system/core/libutils/include/utils/misc.h"
+ }
+ ],
+ "functions" :
+ [
+ {
+ "access" : "private",
+ "function_name" : "android::LogPrinter::printRaw",
+ "linker_set_key" : "_ZN7android10LogPrinter8printRawEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::LogPrinter::printLine",
+ "linker_set_key" : "_ZN7android10LogPrinter9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::LogPrinter::LogPrinter",
+ "linker_set_key" : "_ZN7android10LogPrinterC1EPKc19android_LogPriorityS2_b",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTI19android_LogPriority"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::LogPrinter::LogPrinter",
+ "linker_set_key" : "_ZN7android10LogPrinterC2EPKc19android_LogPriorityS2_b",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTI19android_LogPriority"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::appendArray",
+ "linker_set_key" : "_ZN7android10VectorImpl11appendArrayEPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::setCapacity",
+ "linker_set_key" : "_ZN7android10VectorImpl11setCapacityEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::appendVector",
+ "linker_set_key" : "_ZN7android10VectorImpl12appendVectorERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::editArrayImpl",
+ "linker_set_key" : "_ZN7android10VectorImpl13editArrayImplEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::finish_vector",
+ "linker_set_key" : "_ZN7android10VectorImpl13finish_vectorEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertArrayAt",
+ "linker_set_key" : "_ZN7android10VectorImpl13insertArrayAtEPKvmm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::removeItemsAt",
+ "linker_set_key" : "_ZN7android10VectorImpl13removeItemsAtEmm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertVectorAt",
+ "linker_set_key" : "_ZN7android10VectorImpl14insertVectorAtERKS0_m",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::VectorImpl::release_storage",
+ "linker_set_key" : "_ZN7android10VectorImpl15release_storageEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::editItemLocation",
+ "linker_set_key" : "_ZN7android10VectorImpl16editItemLocationEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::add",
+ "linker_set_key" : "_ZN7android10VectorImpl3addEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::add",
+ "linker_set_key" : "_ZN7android10VectorImpl3addEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::pop",
+ "linker_set_key" : "_ZN7android10VectorImpl3popEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::push",
+ "linker_set_key" : "_ZN7android10VectorImpl4pushEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::push",
+ "linker_set_key" : "_ZN7android10VectorImpl4pushEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::sort",
+ "linker_set_key" : "_ZN7android10VectorImpl4sortEPFiPKvS2_E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiPKvS0_E"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::sort",
+ "linker_set_key" : "_ZN7android10VectorImpl4sortEPFiPKvS2_PvES3_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiPKvS0_PvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::VectorImpl::_grow",
+ "linker_set_key" : "_ZN7android10VectorImpl5_growEmm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::clear",
+ "linker_set_key" : "_ZN7android10VectorImpl5clearEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::resize",
+ "linker_set_key" : "_ZN7android10VectorImpl6resizeEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::VectorImpl::_shrink",
+ "linker_set_key" : "_ZN7android10VectorImpl7_shrinkEmm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertAt",
+ "linker_set_key" : "_ZN7android10VectorImpl8insertAtEPKvmm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertAt",
+ "linker_set_key" : "_ZN7android10VectorImpl8insertAtEmm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::replaceAt",
+ "linker_set_key" : "_ZN7android10VectorImpl9replaceAtEPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::replaceAt",
+ "linker_set_key" : "_ZN7android10VectorImpl9replaceAtEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplC2ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplC2Emj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::~VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::~VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::~VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::operator=",
+ "linker_set_key" : "_ZN7android10VectorImplaSERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIRN7android10VectorImplE",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::uptimeNanos",
+ "linker_set_key" : "_ZN7android11uptimeNanosEv",
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::NativeHandle::create",
+ "linker_set_key" : "_ZN7android12NativeHandle6createEP13native_handleb",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleC1EP13native_handleb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ },
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleC2EP13native_handleb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ },
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::~NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::~NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "function_name" : "android::uptimeMillis",
+ "linker_set_key" : "_ZN7android12uptimeMillisEv",
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::PrefixPrinter::printLine",
+ "linker_set_key" : "_ZN7android13PrefixPrinter9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android13PrefixPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::PrefixPrinter::PrefixPrinter",
+ "linker_set_key" : "_ZN7android13PrefixPrinterC1ERNS_7PrinterEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android13PrefixPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIRN7android7PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::PrefixPrinter::PrefixPrinter",
+ "linker_set_key" : "_ZN7android13PrefixPrinterC2ERNS_7PrinterEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android13PrefixPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIRN7android7PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::LooperCallback::~LooperCallback",
+ "linker_set_key" : "_ZN7android14LooperCallbackD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::LooperCallback::~LooperCallback",
+ "linker_set_key" : "_ZN7android14LooperCallbackD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::LooperCallback::~LooperCallback",
+ "linker_set_key" : "_ZN7android14LooperCallbackD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::MessageHandler::~MessageHandler",
+ "linker_set_key" : "_ZN7android14MessageHandlerD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::MessageHandler::~MessageHandler",
+ "linker_set_key" : "_ZN7android14MessageHandlerD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::MessageHandler::~MessageHandler",
+ "linker_set_key" : "_ZN7android14MessageHandlerD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::String8Printer::printLine",
+ "linker_set_key" : "_ZN7android14String8Printer9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14String8PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::String8Printer::String8Printer",
+ "linker_set_key" : "_ZN7android14String8PrinterC1EPNS_7String8EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14String8PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::String8Printer::String8Printer",
+ "linker_set_key" : "_ZN7android14String8PrinterC2EPNS_7String8EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14String8PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::statusToString",
+ "linker_set_key" : "_ZN7android14statusToStringEi",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTINSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE",
+ "source_file" : "system/core/libutils/include/utils/Errors.h"
+ },
+ {
+ "function_name" : "android::elapsedRealtime",
+ "linker_set_key" : "_ZN7android15elapsedRealtimeEv",
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::add",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl3addEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::merge",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl5mergeERKNS_10VectorImplE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::merge",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl5mergeERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::remove",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl6removeEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplC2ERKNS_10VectorImplE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplC2Emj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::~SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::~SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::~SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::operator=",
+ "linker_set_key" : "_ZN7android16SortedVectorImplaSERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIRN7android16SortedVectorImplE",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::JenkinsHashWhiten",
+ "linker_set_key" : "_ZN7android17JenkinsHashWhitenEj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "function_name" : "android::WeakMessageHandler::handleMessage",
+ "linker_set_key" : "_ZN7android18WeakMessageHandler13handleMessageERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::WeakMessageHandler::WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerC1ERKNS_2wpINS_14MessageHandlerEEE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::WeakMessageHandler::WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerC2ERKNS_2wpINS_14MessageHandlerEEE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::WeakMessageHandler::~WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::WeakMessageHandler::~WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::WeakMessageHandler::~WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::JenkinsHashMixBytes",
+ "linker_set_key" : "_ZN7android19JenkinsHashMixBytesEjPKhm",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "function_name" : "android::elapsedRealtimeNano",
+ "linker_set_key" : "_ZN7android19elapsedRealtimeNanoEv",
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::JenkinsHashMixShorts",
+ "linker_set_key" : "_ZN7android20JenkinsHashMixShortsEjPKtm",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKt"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "function_name" : "android::SimpleLooperCallback::handleEvent",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallback11handleEventEiiPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::SimpleLooperCallback::SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackC1EPFiiiPvE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiiiPvE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::SimpleLooperCallback::SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackC2EPFiiiPvE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiiiPvE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::SimpleLooperCallback::~SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::SimpleLooperCallback::~SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::SimpleLooperCallback::~SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::report_sysprop_change",
+ "linker_set_key" : "_ZN7android21report_sysprop_changeEv",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/misc.h"
+ },
+ {
+ "function_name" : "android::add_sysprop_change_callback",
+ "linker_set_key" : "_ZN7android27add_sysprop_change_callbackEPFvvEi",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFvvE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/misc.h"
+ },
+ {
+ "function_name" : "android::LightRefBase_reportIncStrongRequireStrongFailed",
+ "linker_set_key" : "_ZN7android47LightRefBase_reportIncStrongRequireStrongFailedEPKv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::initTLSKey",
+ "linker_set_key" : "_ZN7android6Looper10initTLSKeyEv",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::sendMessage",
+ "linker_set_key" : "_ZN7android6Looper11sendMessageERKNS_2spINS_14MessageHandlerEEERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::getForThread",
+ "linker_set_key" : "_ZN7android6Looper12getForThreadEv",
+ "return_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::setForThread",
+ "linker_set_key" : "_ZN7android6Looper12setForThreadERKNS_2spIS0_EE",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_6LooperEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::removeMessages",
+ "linker_set_key" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::removeMessages",
+ "linker_set_key" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::threadDestructor",
+ "linker_set_key" : "_ZN7android6Looper16threadDestructorEPv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::sendMessageAtTime",
+ "linker_set_key" : "_ZN7android6Looper17sendMessageAtTimeElRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIl"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::rebuildEpollLocked",
+ "linker_set_key" : "_ZN7android6Looper18rebuildEpollLockedEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::sendMessageDelayed",
+ "linker_set_key" : "_ZN7android6Looper18sendMessageDelayedElRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIl"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::removeSequenceNumberLocked",
+ "linker_set_key" : "_ZN7android6Looper26removeSequenceNumberLockedEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::scheduleEpollRebuildLocked",
+ "linker_set_key" : "_ZN7android6Looper26scheduleEpollRebuildLockedEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::wake",
+ "linker_set_key" : "_ZN7android6Looper4wakeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::addFd",
+ "linker_set_key" : "_ZN7android6Looper5addFdEiiiPFiiiPvES1_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPFiiiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::addFd",
+ "linker_set_key" : "_ZN7android6Looper5addFdEiiiRKNS_2spINS_14LooperCallbackEEEPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14LooperCallbackEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::awoken",
+ "linker_set_key" : "_ZN7android6Looper6awokenEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::pollAll",
+ "linker_set_key" : "_ZN7android6Looper7pollAllEiPiS1_PPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::prepare",
+ "linker_set_key" : "_ZN7android6Looper7prepareEi",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::pollOnce",
+ "linker_set_key" : "_ZN7android6Looper8pollOnceEiPiS1_PPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::removeFd",
+ "linker_set_key" : "_ZN7android6Looper8removeFdEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::pollInner",
+ "linker_set_key" : "_ZN7android6Looper9pollInnerEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::Looper",
+ "linker_set_key" : "_ZN7android6LooperC1Eb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::Looper",
+ "linker_set_key" : "_ZN7android6LooperC2Eb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Looper::~Looper",
+ "linker_set_key" : "_ZN7android6LooperD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Looper::~Looper",
+ "linker_set_key" : "_ZN7android6LooperD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Looper::~Looper",
+ "linker_set_key" : "_ZN7android6LooperD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Thread::readyToRun",
+ "linker_set_key" : "_ZN7android6Thread10readyToRunEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Thread::_threadLoop",
+ "linker_set_key" : "_ZN7android6Thread11_threadLoopEPv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::requestExit",
+ "linker_set_key" : "_ZN7android6Thread11requestExitEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::requestExitAndWait",
+ "linker_set_key" : "_ZN7android6Thread18requestExitAndWaitEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::run",
+ "linker_set_key" : "_ZN7android6Thread3runEPKcim",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::join",
+ "linker_set_key" : "_ZN7android6Thread4joinEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::Thread",
+ "linker_set_key" : "_ZN7android6ThreadC2Eb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::~Thread",
+ "linker_set_key" : "_ZN7android6ThreadD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::~Thread",
+ "linker_set_key" : "_ZN7android6ThreadD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::~Thread",
+ "linker_set_key" : "_ZN7android6ThreadD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::FileMap::advise",
+ "linker_set_key" : "_ZN7android7FileMap6adviseENS0_9MapAdviceE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIN7android7FileMap9MapAdviceE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::create",
+ "linker_set_key" : "_ZN7android7FileMap6createEPKcilmb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIl"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC1EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTION7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC2EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTION7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::~FileMap",
+ "linker_set_key" : "_ZN7android7FileMapD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::~FileMap",
+ "linker_set_key" : "_ZN7android7FileMapD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::operator=",
+ "linker_set_key" : "_ZN7android7FileMapaSEOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTION7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7FileMapE",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::Printer::printFormatLine",
+ "linker_set_key" : "_ZN7android7Printer15printFormatLineEPKcz",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::Printer",
+ "linker_set_key" : "_ZN7android7PrinterC2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::~Printer",
+ "linker_set_key" : "_ZN7android7PrinterD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::~Printer",
+ "linker_set_key" : "_ZN7android7PrinterD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::~Printer",
+ "linker_set_key" : "_ZN7android7PrinterD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onFirstRef",
+ "linker_set_key" : "_ZN7android7RefBase10onFirstRefEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::RefBase::renameRefs",
+ "linker_set_key" : "_ZN7android7RefBase10renameRefsEmRKNS_16ReferenceRenamerE",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android16ReferenceRenamerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::RefBase::renameRefId",
+ "linker_set_key" : "_ZN7android7RefBase11renameRefIdEPNS0_12weakref_typeEPKvS4_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::RefBase::renameRefId",
+ "linker_set_key" : "_ZN7android7RefBase11renameRefIdEPS0_PKvS3_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::attemptIncWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type14attemptIncWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::attemptIncStrong",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type16attemptIncStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::incWeakRequireWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type18incWeakRequireWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::decWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type7decWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::incWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type7incWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::trackMe",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type7trackMeEbb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onLastWeakRef",
+ "linker_set_key" : "_ZN7android7RefBase13onLastWeakRefEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onLastStrongRef",
+ "linker_set_key" : "_ZN7android7RefBase15onLastStrongRefEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::extendObjectLifetime",
+ "linker_set_key" : "_ZN7android7RefBase20extendObjectLifetimeEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onIncStrongAttempted",
+ "linker_set_key" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseC1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseC2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::~RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::~RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::~RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::String8::appendPath",
+ "linker_set_key" : "_ZN7android7String810appendPathEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::lockBuffer",
+ "linker_set_key" : "_ZN7android7String810lockBufferEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String8::real_append",
+ "linker_set_key" : "_ZN7android7String811real_appendEPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::appendFormat",
+ "linker_set_key" : "_ZN7android7String812appendFormatEPKcz",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::unlockBuffer",
+ "linker_set_key" : "_ZN7android7String812unlockBufferEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::unlockBuffer",
+ "linker_set_key" : "_ZN7android7String812unlockBufferEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::appendFormatV",
+ "linker_set_key" : "_ZN7android7String813appendFormatVEPKcSt9__va_list",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTISt9__va_list"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::convertToResPath",
+ "linker_set_key" : "_ZN7android7String816convertToResPathEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::clear",
+ "linker_set_key" : "_ZN7android7String85clearEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKDim",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::append",
+ "linker_set_key" : "_ZN7android7String86appendEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::append",
+ "linker_set_key" : "_ZN7android7String86appendEPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::append",
+ "linker_set_key" : "_ZN7android7String86appendERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::format",
+ "linker_set_key" : "_ZN7android7String86formatEPKcz",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::formatV",
+ "linker_set_key" : "_ZN7android7String87formatVEPKcSt9__va_list",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTISt9__va_list"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::toLower",
+ "linker_set_key" : "_ZN7android7String87toLowerEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::removeAll",
+ "linker_set_key" : "_ZN7android7String89removeAllEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDim",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1ERKNS_8String16E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDim",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2ERKNS_8String16E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::~String8",
+ "linker_set_key" : "_ZN7android7String8D1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::~String8",
+ "linker_set_key" : "_ZN7android7String8D2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::editResize",
+ "linker_set_key" : "_ZN7android8String1610editResizeEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::replaceAll",
+ "linker_set_key" : "_ZN7android8String1610replaceAllEDsDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::allocFromUTF8",
+ "linker_set_key" : "_ZN7android8String1613allocFromUTF8EPKcm",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::allocFromUTF16",
+ "linker_set_key" : "_ZN7android8String1614allocFromUTF16EPKDsm",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::edit",
+ "linker_set_key" : "_ZN7android8String164editEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::alloc",
+ "linker_set_key" : "_ZN7android8String165allocEm",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToEPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToEPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToERKS0_mm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::append",
+ "linker_set_key" : "_ZN7android8String166appendEPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::append",
+ "linker_set_key" : "_ZN7android8String166appendERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::insert",
+ "linker_set_key" : "_ZN7android8String166insertEmPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::insert",
+ "linker_set_key" : "_ZN7android8String166insertEmPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::acquire",
+ "linker_set_key" : "_ZN7android8String167acquireEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::release",
+ "linker_set_key" : "_ZN7android8String167releaseEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTION7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1ERKNS_7String8E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1ERKS0_mm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTION7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKDsm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2ERKNS_7String8E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2ERKS0_mm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::~String16",
+ "linker_set_key" : "_ZN7android8String16D1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::~String16",
+ "linker_set_key" : "_ZN7android8String16D2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::operator=",
+ "linker_set_key" : "_ZN7android8String16aSEOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTION7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIRN7android8String16E",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::FdPrinter::printLine",
+ "linker_set_key" : "_ZN7android9FdPrinter9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9FdPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::FdPrinter::FdPrinter",
+ "linker_set_key" : "_ZN7android9FdPrinterC1EijPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9FdPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::FdPrinter::FdPrinter",
+ "linker_set_key" : "_ZN7android9FdPrinterC2EijPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9FdPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::StopWatch::reset",
+ "linker_set_key" : "_ZN7android9StopWatch5resetEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchC1EPKci",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchC2EPKci",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::~StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::~StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::fromContents",
+ "linker_set_key" : "_ZN7android9Tokenizer12fromContentsERKNS_7String8EPKcPPS0_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::skipDelimiters",
+ "linker_set_key" : "_ZN7android9Tokenizer14skipDelimitersEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::open",
+ "linker_set_key" : "_ZN7android9Tokenizer4openERKNS_7String8EPPS0_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::nextLine",
+ "linker_set_key" : "_ZN7android9Tokenizer8nextLineEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::nextToken",
+ "linker_set_key" : "_ZN7android9Tokenizer9nextTokenEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Tokenizer::Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerC1ERKNS_7String8EPNS_7FileMapEPcbm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Tokenizer::Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerC2ERKNS_7String8EPNS_7FileMapEPcbm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::~Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::~Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::itemLocation",
+ "linker_set_key" : "_ZNK7android10VectorImpl12itemLocationEm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPKv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::capacity",
+ "linker_set_key" : "_ZNK7android10VectorImpl8capacityEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::VectorImpl::itemSize",
+ "linker_set_key" : "_ZNK7android10VectorImpl8itemSizeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::SortedVectorImpl::_indexOrderOf",
+ "linker_set_key" : "_ZNK7android16SortedVectorImpl13_indexOrderOfEPKvPm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::indexOf",
+ "linker_set_key" : "_ZNK7android16SortedVectorImpl7indexOfEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::orderOf",
+ "linker_set_key" : "_ZNK7android16SortedVectorImpl7orderOfEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::Looper::getAllowNonCallbacks",
+ "linker_set_key" : "_ZNK7android6Looper20getAllowNonCallbacksEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::Request::getEpollEvents",
+ "linker_set_key" : "_ZNK7android6Looper7Request14getEpollEventsEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6Looper7RequestE"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::isPolling",
+ "linker_set_key" : "_ZNK7android6Looper9isPollingEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Thread::exitPending",
+ "linker_set_key" : "_ZNK7android6Thread11exitPendingEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::getTid",
+ "linker_set_key" : "_ZNK7android6Thread6getTidEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::isRunning",
+ "linker_set_key" : "_ZNK7android6Thread9isRunningEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_destroy",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE10do_destroyEPvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_construct",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE12do_constructEPvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_move_forward",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE15do_move_forwardEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_move_backward",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE16do_move_backwardEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_copy",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE7do_copyEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_splat",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE8do_splatEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_destroy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE10do_destroyEPvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_construct",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE12do_constructEPvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_move_forward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE15do_move_forwardEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_move_backward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE16do_move_backwardEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_copy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE7do_copyEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_splat",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE8do_splatEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_destroy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE10do_destroyEPvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_construct",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE12do_constructEPvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_move_forward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE15do_move_forwardEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_move_backward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE16do_move_backwardEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_copy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE7do_copyEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_splat",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE8do_splatEPvPKvm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "function_name" : "android::RefBase::createWeak",
+ "linker_set_key" : "_ZNK7android7RefBase10createWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::getWeakRefs",
+ "linker_set_key" : "_ZNK7android7RefBase11getWeakRefsEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::getWeakCount",
+ "linker_set_key" : "_ZNK7android7RefBase12weakref_type12getWeakCountEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::refBase",
+ "linker_set_key" : "_ZNK7android7RefBase12weakref_type7refBaseEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "return_type" : "_ZTIPN7android7RefBaseE",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::printRefs",
+ "linker_set_key" : "_ZNK7android7RefBase12weakref_type9printRefsEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::forceIncStrong",
+ "linker_set_key" : "_ZNK7android7RefBase14forceIncStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::getStrongCount",
+ "linker_set_key" : "_ZNK7android7RefBase14getStrongCountEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::incStrongRequireStrong",
+ "linker_set_key" : "_ZNK7android7RefBase22incStrongRequireStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::decStrong",
+ "linker_set_key" : "_ZNK7android7RefBase9decStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::incStrong",
+ "linker_set_key" : "_ZNK7android7RefBase9incStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::String8::getPathDir",
+ "linker_set_key" : "_ZNK7android7String810getPathDirEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getBasePath",
+ "linker_set_key" : "_ZNK7android7String811getBasePathEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathLeaf",
+ "linker_set_key" : "_ZNK7android7String811getPathLeafEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String8::find_extension",
+ "linker_set_key" : "_ZNK7android7String814find_extensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathExtension",
+ "linker_set_key" : "_ZNK7android7String816getPathExtensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::find",
+ "linker_set_key" : "_ZNK7android7String84findEPKcm",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::length",
+ "linker_set_key" : "_ZNK7android7String86lengthEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::walkPath",
+ "linker_set_key" : "_ZNK7android7String88walkPathEPS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String16::startsWith",
+ "linker_set_key" : "_ZNK7android8String1610startsWithEPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::startsWith",
+ "linker_set_key" : "_ZNK7android8String1610startsWithERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::isStaticString",
+ "linker_set_key" : "_ZNK7android8String1614isStaticStringEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::staticStringSize",
+ "linker_set_key" : "_ZNK7android8String1616staticStringSizeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::size",
+ "linker_set_key" : "_ZNK7android8String164sizeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::contains",
+ "linker_set_key" : "_ZNK7android8String168containsEPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::findLast",
+ "linker_set_key" : "_ZNK7android8String168findLastEDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::findFirst",
+ "linker_set_key" : "_ZNK7android8String169findFirstEDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::StopWatch::elapsedTime",
+ "linker_set_key" : "_ZNK7android9StopWatch11elapsedTimeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::name",
+ "linker_set_key" : "_ZNK7android9StopWatch4nameEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIPKc",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::getLocation",
+ "linker_set_key" : "_ZNK7android9Tokenizer11getLocationEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::peekRemainderOfLine",
+ "linker_set_key" : "_ZNK7android9Tokenizer19peekRemainderOfLineEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "androidCreateRawThreadEtc",
+ "linker_set_key" : "androidCreateRawThreadEtc",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidCreateThread",
+ "linker_set_key" : "androidCreateThread",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidCreateThreadEtc",
+ "linker_set_key" : "androidCreateThreadEtc",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidGetThreadId",
+ "linker_set_key" : "androidGetThreadId",
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidGetThreadPriority",
+ "linker_set_key" : "androidGetThreadPriority",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidSetCreateThreadFunc",
+ "linker_set_key" : "androidSetCreateThreadFunc",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPFiPvES_PKcimPS_E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidSetThreadName",
+ "linker_set_key" : "androidSetThreadName",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidSetThreadPriority",
+ "linker_set_key" : "androidSetThreadPriority",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "strcmp16",
+ "linker_set_key" : "strcmp16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strlen16",
+ "linker_set_key" : "strlen16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strncmp16",
+ "linker_set_key" : "strncmp16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strnlen16",
+ "linker_set_key" : "strnlen16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIm",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strstr16",
+ "linker_set_key" : "strstr16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strzcmp16",
+ "linker_set_key" : "strzcmp16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "systemTime",
+ "linker_set_key" : "systemTime",
+ "parameters" :
+ [
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/Timers.h"
+ },
+ {
+ "function_name" : "toMillisecondTimeoutDelay",
+ "linker_set_key" : "toMillisecondTimeoutDelay",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIl"
+ },
+ {
+ "referenced_type" : "_ZTIl"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Timers.h"
+ },
+ {
+ "function_name" : "utf16_to_utf8",
+ "linker_set_key" : "utf16_to_utf8",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf16_to_utf8_length",
+ "linker_set_key" : "utf16_to_utf8_length",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf32_from_utf8_at",
+ "linker_set_key" : "utf32_from_utf8_at",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPm"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf32_to_utf8",
+ "linker_set_key" : "utf32_to_utf8",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf32_to_utf8_length",
+ "linker_set_key" : "utf32_to_utf8_length",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf8_to_utf16",
+ "linker_set_key" : "utf8_to_utf16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf8_to_utf16_length",
+ "linker_set_key" : "utf8_to_utf16_length",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf8_to_utf16_no_null_terminator",
+ "linker_set_key" : "utf8_to_utf16_no_null_terminator",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "referenced_type" : "_ZTIPDs"
+ },
+ {
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ }
+ ],
+ "global_vars" :
+ [
+ {
+ "access" : "private",
+ "linker_set_key" : "_ZN7android7FileMap9mPageSizeE",
+ "name" : "android::FileMap::mPageSize",
+ "referenced_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ }
+ ],
+ "lvalue_reference_types" :
+ [
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRA1_KDs",
+ "name" : "const char16_t (&)[1]",
+ "referenced_type" : "_ZTIA1_KDs",
+ "self_type" : "_ZTIRA1_KDs",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android10VectorImplE",
+ "name" : "const android::VectorImpl &",
+ "referenced_type" : "_ZTIKN7android10VectorImplE",
+ "self_type" : "_ZTIRKN7android10VectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android16ReferenceRenamerE",
+ "name" : "const android::ReferenceRenamer &",
+ "referenced_type" : "_ZTIKN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIRKN7android16ReferenceRenamerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android16SortedVectorImplE",
+ "name" : "const android::SortedVectorImpl &",
+ "referenced_type" : "_ZTIKN7android16SortedVectorImplE",
+ "self_type" : "_ZTIRKN7android16SortedVectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android28sysprop_change_callback_infoE",
+ "name" : "const android::sysprop_change_callback_info &",
+ "referenced_type" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIRKN7android28sysprop_change_callback_infoE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android2spINS_14LooperCallbackEEE",
+ "name" : "const android::sp<android::LooperCallback> &",
+ "referenced_type" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIRKN7android2spINS_14LooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android2spINS_14MessageHandlerEEE",
+ "name" : "const android::sp<android::MessageHandler> &",
+ "referenced_type" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "const android::sp<android::SimpleLooperCallback> &",
+ "referenced_type" : "_ZTIKN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIRKN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android2spINS_6LooperEEE",
+ "name" : "const android::sp<android::Looper> &",
+ "referenced_type" : "_ZTIKN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIRKN7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android2spINS_6ThreadEEE",
+ "name" : "const android::sp<android::Thread> &",
+ "referenced_type" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIRKN7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE",
+ "name" : "const android::wp<android::MessageHandler> &",
+ "referenced_type" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android6Looper15MessageEnvelopeE",
+ "name" : "const android::Looper::MessageEnvelope &",
+ "referenced_type" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIRKN7android6Looper15MessageEnvelopeE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android6Looper8ResponseE",
+ "name" : "const android::Looper::Response &",
+ "referenced_type" : "_ZTIKN7android6Looper8ResponseE",
+ "self_type" : "_ZTIRKN7android6Looper8ResponseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "const android::Vector<android::sysprop_change_callback_info> &",
+ "referenced_type" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIRKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android7MessageE",
+ "name" : "const android::Message &",
+ "referenced_type" : "_ZTIKN7android7MessageE",
+ "self_type" : "_ZTIRKN7android7MessageE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android7String8E",
+ "name" : "const android::String8 &",
+ "referenced_type" : "_ZTIKN7android7String8E",
+ "self_type" : "_ZTIRKN7android7String8E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android8String1610StaticDataILm1EEE",
+ "name" : "const android::String16::StaticData<1> &",
+ "referenced_type" : "_ZTIKN7android8String1610StaticDataILm1EEE",
+ "self_type" : "_ZTIRKN7android8String1610StaticDataILm1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKN7android8String16E",
+ "name" : "const android::String16 &",
+ "referenced_type" : "_ZTIKN7android8String16E",
+ "self_type" : "_ZTIRKN7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKa",
+ "name" : "const signed char &",
+ "referenced_type" : "_ZTIKa",
+ "self_type" : "_ZTIRKa",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKb",
+ "name" : "const bool &",
+ "referenced_type" : "_ZTIKb",
+ "self_type" : "_ZTIRKb",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKd",
+ "name" : "const double &",
+ "referenced_type" : "_ZTIKd",
+ "self_type" : "_ZTIRKd",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKf",
+ "name" : "const float &",
+ "referenced_type" : "_ZTIKf",
+ "self_type" : "_ZTIRKf",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKh",
+ "name" : "const unsigned char &",
+ "referenced_type" : "_ZTIKh",
+ "self_type" : "_ZTIRKh",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKi",
+ "name" : "const int &",
+ "referenced_type" : "_ZTIKi",
+ "self_type" : "_ZTIRKi",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKj",
+ "name" : "const unsigned int &",
+ "referenced_type" : "_ZTIKj",
+ "self_type" : "_ZTIRKj",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKl",
+ "name" : "const long &",
+ "referenced_type" : "_ZTIKl",
+ "self_type" : "_ZTIRKl",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKm",
+ "name" : "const unsigned long &",
+ "referenced_type" : "_ZTIKm",
+ "self_type" : "_ZTIRKm",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKs",
+ "name" : "const short &",
+ "referenced_type" : "_ZTIKs",
+ "self_type" : "_ZTIRKs",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRKt",
+ "name" : "const unsigned short &",
+ "referenced_type" : "_ZTIKt",
+ "self_type" : "_ZTIRKt",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android10VectorImplE",
+ "name" : "android::VectorImpl &",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIRN7android10VectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android16SortedVectorImplE",
+ "name" : "android::SortedVectorImpl &",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIRN7android16SortedVectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android2spINS_14LooperCallbackEEE",
+ "name" : "android::sp<android::LooperCallback> &",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIRN7android2spINS_14LooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler> &",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIRN7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback> &",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIRN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper> &",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIRN7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread> &",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIRN7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android5MutexE",
+ "name" : "android::Mutex &",
+ "referenced_type" : "_ZTIN7android5MutexE",
+ "self_type" : "_ZTIRN7android5MutexE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android6Looper8ResponseE",
+ "name" : "android::Looper::Response &",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIRN7android6Looper8ResponseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android6RWLockE",
+ "name" : "android::RWLock &",
+ "referenced_type" : "_ZTIN7android6RWLockE",
+ "self_type" : "_ZTIRN7android6RWLockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::Vector<android::sysprop_change_callback_info> &",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIRN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android7FileMapE",
+ "name" : "android::FileMap &",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIRN7android7FileMapE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android7PrinterE",
+ "name" : "android::Printer &",
+ "referenced_type" : "_ZTIN7android7PrinterE",
+ "self_type" : "_ZTIRN7android7PrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android7String8E",
+ "name" : "android::String8 &",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIRN7android7String8E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRN7android8String16E",
+ "name" : "android::String16 &",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIRN7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRP13native_handle",
+ "name" : "native_handle *&",
+ "referenced_type" : "_ZTIP13native_handle",
+ "self_type" : "_ZTIRP13native_handle",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRPFiiiPvE",
+ "name" : "int (*&)(int, int, void *)",
+ "referenced_type" : "_ZTIPFiiiPvE",
+ "self_type" : "_ZTIRPFiiiPvE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIRb",
+ "name" : "bool &",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIRb",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ }
+ ],
+ "pointer_types" :
+ [
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP13native_handle",
+ "name" : "native_handle *",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTIP13native_handle",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP18android_flex_plane",
+ "name" : "android_flex_plane *",
+ "referenced_type" : "_ZTI18android_flex_plane",
+ "self_type" : "_ZTIP18android_flex_plane",
+ "size" : 8,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP3DIR",
+ "name" : "DIR *",
+ "referenced_type" : "_ZTI3DIR",
+ "self_type" : "_ZTIP3DIR",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP7__sFILE",
+ "name" : "__sFILE *",
+ "referenced_type" : "_ZTI7__sFILE",
+ "self_type" : "_ZTIP7__sFILE",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIP7log_msg",
+ "name" : "log_msg *",
+ "referenced_type" : "_ZTI7log_msg",
+ "self_type" : "_ZTIP7log_msg",
+ "size" : 8,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPDs",
+ "name" : "char16_t *",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIPDs",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFiPFiPvES_PKcimPS_E",
+ "name" : "int (*)(int (*)(void *), void *, const char *, int, unsigned long, void **)",
+ "referenced_type" : "_ZTIFiPFiPvES_PKcimPS_E",
+ "self_type" : "_ZTIPFiPFiPvES_PKcimPS_E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFiPKvS0_E",
+ "name" : "int (*)(const void *, const void *)",
+ "referenced_type" : "_ZTIFiPKvS0_E",
+ "self_type" : "_ZTIPFiPKvS0_E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFiPKvS0_PvE",
+ "name" : "int (*)(const void *, const void *, void *)",
+ "referenced_type" : "_ZTIFiPKvS0_PvE",
+ "self_type" : "_ZTIPFiPKvS0_PvE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFiPvE",
+ "name" : "int (*)(void *)",
+ "referenced_type" : "_ZTIFiPvE",
+ "self_type" : "_ZTIPFiPvE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFiiiPvE",
+ "name" : "int (*)(int, int, void *)",
+ "referenced_type" : "_ZTIFiiiPvE",
+ "self_type" : "_ZTIPFiiiPvE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPFvvE",
+ "name" : "void (*)()",
+ "referenced_type" : "_ZTIFvvE",
+ "self_type" : "_ZTIPFvvE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/misc.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/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPK7log_msg",
+ "name" : "const log_msg *",
+ "referenced_type" : "_ZTIK7log_msg",
+ "self_type" : "_ZTIPK7log_msg",
+ "size" : 8,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKDi",
+ "name" : "const char32_t *",
+ "referenced_type" : "_ZTIKDi",
+ "self_type" : "_ZTIPKDi",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKDs",
+ "name" : "const char16_t *",
+ "referenced_type" : "_ZTIKDs",
+ "self_type" : "_ZTIPKDs",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android10VectorImplE",
+ "name" : "const android::VectorImpl *",
+ "referenced_type" : "_ZTIKN7android10VectorImplE",
+ "self_type" : "_ZTIPKN7android10VectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "const android::LightRefBase<android::NativeHandle> *",
+ "referenced_type" : "_ZTIKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIPKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android12NativeHandleE",
+ "name" : "const android::NativeHandle *",
+ "referenced_type" : "_ZTIKN7android12NativeHandleE",
+ "self_type" : "_ZTIPKN7android12NativeHandleE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android16SortedVectorImplE",
+ "name" : "const android::SortedVectorImpl *",
+ "referenced_type" : "_ZTIKN7android16SortedVectorImplE",
+ "self_type" : "_ZTIPKN7android16SortedVectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android28sysprop_change_callback_infoE",
+ "name" : "const android::sysprop_change_callback_info *",
+ "referenced_type" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIPKN7android28sysprop_change_callback_infoE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android2spINS_14LooperCallbackEEE",
+ "name" : "const android::sp<android::LooperCallback> *",
+ "referenced_type" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIPKN7android2spINS_14LooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android2spINS_14MessageHandlerEEE",
+ "name" : "const android::sp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPKN7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android2spINS_6LooperEEE",
+ "name" : "const android::sp<android::Looper> *",
+ "referenced_type" : "_ZTIKN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIPKN7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android2spINS_6ThreadEEE",
+ "name" : "const android::sp<android::Thread> *",
+ "referenced_type" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIPKN7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android2wpINS_14MessageHandlerEEE",
+ "name" : "const android::wp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPKN7android2wpINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android2wpINS_6ThreadEEE",
+ "name" : "const android::wp<android::Thread> *",
+ "referenced_type" : "_ZTIKN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIPKN7android2wpINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android4base11borrowed_fdE",
+ "name" : "const android::base::borrowed_fd *",
+ "referenced_type" : "_ZTIKN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIPKN7android4base11borrowed_fdE",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "const android::base::unique_fd_impl<android::base::DefaultCloser> *",
+ "referenced_type" : "_ZTIKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIPKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6Looper15MessageEnvelopeE",
+ "name" : "const android::Looper::MessageEnvelope *",
+ "referenced_type" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIPKN7android6Looper15MessageEnvelopeE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6Looper7RequestE",
+ "name" : "const android::Looper::Request *",
+ "referenced_type" : "_ZTIKN7android6Looper7RequestE",
+ "self_type" : "_ZTIPKN7android6Looper7RequestE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6Looper8ResponseE",
+ "name" : "const android::Looper::Response *",
+ "referenced_type" : "_ZTIKN7android6Looper8ResponseE",
+ "self_type" : "_ZTIPKN7android6Looper8ResponseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6LooperE",
+ "name" : "const android::Looper *",
+ "referenced_type" : "_ZTIKN7android6LooperE",
+ "self_type" : "_ZTIPKN7android6LooperE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6ThreadE",
+ "name" : "const android::Thread *",
+ "referenced_type" : "_ZTIKN7android6ThreadE",
+ "self_type" : "_ZTIPKN7android6ThreadE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "const android::Vector<android::sysprop_change_callback_info> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "const android::Vector<android::Looper::MessageEnvelope> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "const android::Vector<android::Looper::Response> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_7String8EEE",
+ "name" : "const android::Vector<android::String8> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_7String8EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android7FileMapE",
+ "name" : "const android::FileMap *",
+ "referenced_type" : "_ZTIKN7android7FileMapE",
+ "self_type" : "_ZTIPKN7android7FileMapE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android7RefBase12weakref_typeE",
+ "name" : "const android::RefBase::weakref_type *",
+ "referenced_type" : "_ZTIKN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIPKN7android7RefBase12weakref_typeE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android7RefBaseE",
+ "name" : "const android::RefBase *",
+ "referenced_type" : "_ZTIKN7android7RefBaseE",
+ "self_type" : "_ZTIPKN7android7RefBaseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android7String8E",
+ "name" : "const android::String8 *",
+ "referenced_type" : "_ZTIKN7android7String8E",
+ "self_type" : "_ZTIPKN7android7String8E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android8String16E",
+ "name" : "const android::String16 *",
+ "referenced_type" : "_ZTIKN7android8String16E",
+ "self_type" : "_ZTIPKN7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android9CallStackE",
+ "name" : "const android::CallStack *",
+ "referenced_type" : "_ZTIKN7android9CallStackE",
+ "self_type" : "_ZTIPKN7android9CallStackE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android9StopWatchE",
+ "name" : "const android::StopWatch *",
+ "referenced_type" : "_ZTIKN7android9StopWatchE",
+ "self_type" : "_ZTIPKN7android9StopWatchE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKN7android9TokenizerE",
+ "name" : "const android::Tokenizer *",
+ "referenced_type" : "_ZTIKN7android9TokenizerE",
+ "self_type" : "_ZTIPKN7android9TokenizerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKc",
+ "name" : "const char *",
+ "referenced_type" : "_ZTIKc",
+ "self_type" : "_ZTIPKc",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKh",
+ "name" : "const unsigned char *",
+ "referenced_type" : "_ZTIKh",
+ "self_type" : "_ZTIPKh",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKt",
+ "name" : "const unsigned short *",
+ "referenced_type" : "_ZTIKt",
+ "self_type" : "_ZTIPKt",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPKv",
+ "name" : "const void *",
+ "referenced_type" : "_ZTIKv",
+ "self_type" : "_ZTIPKv",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android10LogPrinterE",
+ "name" : "android::LogPrinter *",
+ "referenced_type" : "_ZTIN7android10LogPrinterE",
+ "self_type" : "_ZTIPN7android10LogPrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android10VectorImplE",
+ "name" : "android::VectorImpl *",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIPN7android10VectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android11ScopedTraceE",
+ "name" : "android::ScopedTrace *",
+ "referenced_type" : "_ZTIN7android11ScopedTraceE",
+ "self_type" : "_ZTIPN7android11ScopedTraceE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Trace.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "android::LightRefBase<android::NativeHandle> *",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIPN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android12NativeHandleE",
+ "name" : "android::NativeHandle *",
+ "referenced_type" : "_ZTIN7android12NativeHandleE",
+ "self_type" : "_ZTIPN7android12NativeHandleE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android13PrefixPrinterE",
+ "name" : "android::PrefixPrinter *",
+ "referenced_type" : "_ZTIN7android13PrefixPrinterE",
+ "self_type" : "_ZTIPN7android13PrefixPrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android14LooperCallbackE",
+ "name" : "android::LooperCallback *",
+ "referenced_type" : "_ZTIN7android14LooperCallbackE",
+ "self_type" : "_ZTIPN7android14LooperCallbackE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android14MessageHandlerE",
+ "name" : "android::MessageHandler *",
+ "referenced_type" : "_ZTIN7android14MessageHandlerE",
+ "self_type" : "_ZTIPN7android14MessageHandlerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android14StaticString16ILm1EEE",
+ "name" : "android::StaticString16<1> *",
+ "referenced_type" : "_ZTIN7android14StaticString16ILm1EEE",
+ "self_type" : "_ZTIPN7android14StaticString16ILm1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android14String8PrinterE",
+ "name" : "android::String8Printer *",
+ "referenced_type" : "_ZTIN7android14String8PrinterE",
+ "self_type" : "_ZTIPN7android14String8PrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android16ReferenceRenamerE",
+ "name" : "android::ReferenceRenamer *",
+ "referenced_type" : "_ZTIN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIPN7android16ReferenceRenamerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android16SortedVectorImplE",
+ "name" : "android::SortedVectorImpl *",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIPN7android16SortedVectorImplE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android18WeakMessageHandlerE",
+ "name" : "android::WeakMessageHandler *",
+ "referenced_type" : "_ZTIN7android18WeakMessageHandlerE",
+ "self_type" : "_ZTIPN7android18WeakMessageHandlerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android19VirtualLightRefBaseE",
+ "name" : "android::VirtualLightRefBase *",
+ "referenced_type" : "_ZTIN7android19VirtualLightRefBaseE",
+ "self_type" : "_ZTIPN7android19VirtualLightRefBaseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android20SimpleLooperCallbackE",
+ "name" : "android::SimpleLooperCallback *",
+ "referenced_type" : "_ZTIN7android20SimpleLooperCallbackE",
+ "self_type" : "_ZTIPN7android20SimpleLooperCallbackE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android28sysprop_change_callback_infoE",
+ "name" : "android::sysprop_change_callback_info *",
+ "referenced_type" : "_ZTIN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIPN7android28sysprop_change_callback_infoE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2spINS_12NativeHandleEEE",
+ "name" : "android::sp<android::NativeHandle> *",
+ "referenced_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "self_type" : "_ZTIPN7android2spINS_12NativeHandleEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2spINS_14LooperCallbackEEE",
+ "name" : "android::sp<android::LooperCallback> *",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIPN7android2spINS_14LooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPN7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback> *",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIPN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper> *",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIPN7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread> *",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIPN7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2wpINS_14MessageHandlerEEE",
+ "name" : "android::wp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPN7android2wpINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android2wpINS_6ThreadEEE",
+ "name" : "android::wp<android::Thread> *",
+ "referenced_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIPN7android2wpINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android4base11borrowed_fdE",
+ "name" : "android::base::borrowed_fd *",
+ "referenced_type" : "_ZTIN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIPN7android4base11borrowed_fdE",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "android::base::unique_fd_impl<android::base::DefaultCloser> *",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIPN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android5Mutex8AutolockE",
+ "name" : "android::Mutex::Autolock *",
+ "referenced_type" : "_ZTIN7android5Mutex8AutolockE",
+ "self_type" : "_ZTIPN7android5Mutex8AutolockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android5MutexE",
+ "name" : "android::Mutex *",
+ "referenced_type" : "_ZTIN7android5MutexE",
+ "self_type" : "_ZTIPN7android5MutexE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6Looper15MessageEnvelopeE",
+ "name" : "android::Looper::MessageEnvelope *",
+ "referenced_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIPN7android6Looper15MessageEnvelopeE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6Looper8ResponseE",
+ "name" : "android::Looper::Response *",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIPN7android6Looper8ResponseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6LooperE",
+ "name" : "android::Looper *",
+ "referenced_type" : "_ZTIN7android6LooperE",
+ "self_type" : "_ZTIPN7android6LooperE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6RWLock9AutoRLockE",
+ "name" : "android::RWLock::AutoRLock *",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoRLockE",
+ "self_type" : "_ZTIPN7android6RWLock9AutoRLockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6RWLock9AutoWLockE",
+ "name" : "android::RWLock::AutoWLock *",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoWLockE",
+ "self_type" : "_ZTIPN7android6RWLock9AutoWLockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6RWLockE",
+ "name" : "android::RWLock *",
+ "referenced_type" : "_ZTIN7android6RWLockE",
+ "self_type" : "_ZTIPN7android6RWLockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6ThreadE",
+ "name" : "android::Thread *",
+ "referenced_type" : "_ZTIN7android6ThreadE",
+ "self_type" : "_ZTIPN7android6ThreadE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::Vector<android::sysprop_change_callback_info> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIPN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::Vector<android::Looper::MessageEnvelope> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIPN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "android::Vector<android::Looper::Response> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIPN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_7String8EEE",
+ "name" : "android::Vector<android::String8> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIPN7android6VectorINS_7String8EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7FileMapE",
+ "name" : "android::FileMap *",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIPN7android7FileMapE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7MessageE",
+ "name" : "android::Message *",
+ "referenced_type" : "_ZTIN7android7MessageE",
+ "self_type" : "_ZTIPN7android7MessageE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7PrinterE",
+ "name" : "android::Printer *",
+ "referenced_type" : "_ZTIN7android7PrinterE",
+ "self_type" : "_ZTIPN7android7PrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7RefBase12weakref_implE",
+ "name" : "android::RefBase::weakref_impl *",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_implE",
+ "self_type" : "_ZTIPN7android7RefBase12weakref_implE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "name" : "android::RefBase::weakref_type *",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7RefBaseE",
+ "name" : "android::RefBase *",
+ "referenced_type" : "_ZTIN7android7RefBaseE",
+ "self_type" : "_ZTIPN7android7RefBaseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android7String8E",
+ "name" : "android::String8 *",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIPN7android7String8E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android8String1610StaticDataILm1EEE",
+ "name" : "android::String16::StaticData<1> *",
+ "referenced_type" : "_ZTIN7android8String1610StaticDataILm1EEE",
+ "self_type" : "_ZTIPN7android8String1610StaticDataILm1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android8String16E",
+ "name" : "android::String16 *",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIPN7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android9CallStack12StackDeleterE",
+ "name" : "android::CallStack::StackDeleter *",
+ "referenced_type" : "_ZTIN7android9CallStack12StackDeleterE",
+ "self_type" : "_ZTIPN7android9CallStack12StackDeleterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android9CallStackE",
+ "name" : "android::CallStack *",
+ "referenced_type" : "_ZTIN7android9CallStackE",
+ "self_type" : "_ZTIPN7android9CallStackE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android9ConditionE",
+ "name" : "android::Condition *",
+ "referenced_type" : "_ZTIN7android9ConditionE",
+ "self_type" : "_ZTIPN7android9ConditionE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Condition.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android9FdPrinterE",
+ "name" : "android::FdPrinter *",
+ "referenced_type" : "_ZTIN7android9FdPrinterE",
+ "self_type" : "_ZTIPN7android9FdPrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android9StopWatchE",
+ "name" : "android::StopWatch *",
+ "referenced_type" : "_ZTIN7android9StopWatchE",
+ "self_type" : "_ZTIPN7android9StopWatchE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPN7android9TokenizerE",
+ "name" : "android::Tokenizer *",
+ "referenced_type" : "_ZTIN7android9TokenizerE",
+ "self_type" : "_ZTIPN7android9TokenizerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPPN7android9TokenizerE",
+ "name" : "android::Tokenizer **",
+ "referenced_type" : "_ZTIPN7android9TokenizerE",
+ "self_type" : "_ZTIPPN7android9TokenizerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPPv",
+ "name" : "void **",
+ "referenced_type" : "_ZTIPv",
+ "self_type" : "_ZTIPPv",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPc",
+ "name" : "char *",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIPc",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPh",
+ "name" : "unsigned char *",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIPh",
+ "size" : 8,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPi",
+ "name" : "int *",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIPi",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPm",
+ "name" : "unsigned long *",
+ "referenced_type" : "_ZTIm",
+ "self_type" : "_ZTIPm",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIPv",
+ "name" : "void *",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIPv",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ }
+ ],
+ "qualified_types" :
+ [
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIA1_KDs",
+ "name" : "const char16_t[1]",
+ "referenced_type" : "_ZTIA1_Ds",
+ "self_type" : "_ZTIA1_KDs",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "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/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK7log_msg",
+ "name" : "const log_msg",
+ "referenced_type" : "_ZTI7log_msg",
+ "self_type" : "_ZTIK7log_msg",
+ "size" : 5124,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKDi",
+ "name" : "const char32_t",
+ "referenced_type" : "_ZTIDi",
+ "self_type" : "_ZTIKDi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKDs",
+ "name" : "const char16_t",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIKDs",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android10VectorImplE",
+ "name" : "const android::VectorImpl",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIKN7android10VectorImplE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "const android::LightRefBase<android::NativeHandle>",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android12NativeHandleE",
+ "name" : "const android::NativeHandle",
+ "referenced_type" : "_ZTIN7android12NativeHandleE",
+ "self_type" : "_ZTIKN7android12NativeHandleE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android16ReferenceRenamerE",
+ "name" : "const android::ReferenceRenamer",
+ "referenced_type" : "_ZTIN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIKN7android16ReferenceRenamerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android16SortedVectorImplE",
+ "name" : "const android::SortedVectorImpl",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIKN7android16SortedVectorImplE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "name" : "const android::sysprop_change_callback_info",
+ "referenced_type" : "_ZTIN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "name" : "const android::sp<android::LooperCallback>",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "name" : "const android::sp<android::MessageHandler>",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "const android::sp<android::SimpleLooperCallback>",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIKN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_6LooperEEE",
+ "name" : "const android::sp<android::Looper>",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIKN7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "name" : "const android::sp<android::Thread>",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "name" : "const android::wp<android::MessageHandler>",
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2wpINS_6ThreadEEE",
+ "name" : "const android::wp<android::Thread>",
+ "referenced_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIKN7android2wpINS_6ThreadEEE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android4base11borrowed_fdE",
+ "name" : "const android::base::borrowed_fd",
+ "referenced_type" : "_ZTIN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIKN7android4base11borrowed_fdE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "const android::base::unique_fd_impl<android::base::DefaultCloser>",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "name" : "const android::Looper::MessageEnvelope",
+ "referenced_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6Looper7RequestE",
+ "name" : "const android::Looper::Request",
+ "referenced_type" : "_ZTIN7android6Looper7RequestE",
+ "self_type" : "_ZTIKN7android6Looper7RequestE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6Looper8ResponseE",
+ "name" : "const android::Looper::Response",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIKN7android6Looper8ResponseE",
+ "size" : 48,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6LooperE",
+ "name" : "const android::Looper",
+ "referenced_type" : "_ZTIN7android6LooperE",
+ "self_type" : "_ZTIKN7android6LooperE",
+ "size" : 264,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6ThreadE",
+ "name" : "const android::Thread",
+ "referenced_type" : "_ZTIN7android6ThreadE",
+ "self_type" : "_ZTIKN7android6ThreadE",
+ "size" : 152,
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "const android::Vector<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "const android::Vector<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "const android::Vector<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIKN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_7String8EEE",
+ "name" : "const android::Vector<android::String8>",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIKN7android6VectorINS_7String8EEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7FileMapE",
+ "name" : "const android::FileMap",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIKN7android7FileMapE",
+ "size" : 48,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7MessageE",
+ "name" : "const android::Message",
+ "referenced_type" : "_ZTIN7android7MessageE",
+ "self_type" : "_ZTIKN7android7MessageE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7RefBase12weakref_typeE",
+ "name" : "const android::RefBase::weakref_type",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIKN7android7RefBase12weakref_typeE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7RefBaseE",
+ "name" : "const android::RefBase",
+ "referenced_type" : "_ZTIN7android7RefBaseE",
+ "self_type" : "_ZTIKN7android7RefBaseE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7String8E",
+ "name" : "const android::String8",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIKN7android7String8E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android8String1610StaticDataILm1EEE",
+ "name" : "const android::String16::StaticData<1>",
+ "referenced_type" : "_ZTIN7android8String1610StaticDataILm1EEE",
+ "self_type" : "_ZTIKN7android8String1610StaticDataILm1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android8String16E",
+ "name" : "const android::String16",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIKN7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android9CallStackE",
+ "name" : "const android::CallStack",
+ "referenced_type" : "_ZTIN7android9CallStackE",
+ "self_type" : "_ZTIKN7android9CallStackE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android9StopWatchE",
+ "name" : "const android::StopWatch",
+ "referenced_type" : "_ZTIN7android9StopWatchE",
+ "self_type" : "_ZTIKN7android9StopWatchE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android9TokenizerE",
+ "name" : "const android::Tokenizer",
+ "referenced_type" : "_ZTIN7android9TokenizerE",
+ "self_type" : "_ZTIKN7android9TokenizerE",
+ "size" : 56,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKPKc",
+ "name" : "const char *const",
+ "referenced_type" : "_ZTIPKc",
+ "self_type" : "_ZTIKPKc",
+ "size" : 8,
+ "source_file" : "system/core/libprocessgroup/include/processgroup/processgroup.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKPN7android7RefBase12weakref_implE",
+ "name" : "android::RefBase::weakref_impl *const",
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_implE",
+ "self_type" : "_ZTIKPN7android7RefBase12weakref_implE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKa",
+ "name" : "const signed char",
+ "referenced_type" : "_ZTIa",
+ "self_type" : "_ZTIKa",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKb",
+ "name" : "const bool",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIKb",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.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/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKd",
+ "name" : "const double",
+ "referenced_type" : "_ZTId",
+ "self_type" : "_ZTIKd",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKf",
+ "name" : "const float",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIKf",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKh",
+ "name" : "const unsigned char",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIKh",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKi",
+ "name" : "const int",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIKi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKj",
+ "name" : "const unsigned int",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIKj",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKl",
+ "name" : "const long",
+ "referenced_type" : "_ZTIl",
+ "self_type" : "_ZTIKl",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKm",
+ "name" : "const unsigned long",
+ "referenced_type" : "_ZTIm",
+ "self_type" : "_ZTIKm",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKs",
+ "name" : "const short",
+ "referenced_type" : "_ZTIs",
+ "self_type" : "_ZTIKs",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKt",
+ "name" : "const unsigned short",
+ "referenced_type" : "_ZTIt",
+ "self_type" : "_ZTIKt",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKv",
+ "name" : "const void",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIKv",
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 1,
+ "is_volatile" : true,
+ "linker_set_key" : "_ZTIVb",
+ "name" : "volatile bool",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIVb",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ }
+ ],
+ "record_types" :
+ [
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "len",
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "field_name" : "hdr_size",
+ "field_offset" : 16,
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "field_name" : "pid",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "tid",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "sec",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "nsec",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "lid",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "uid",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "linker_set_key" : "_ZTI12logger_entry",
+ "name" : "logger_entry",
+ "referenced_type" : "_ZTI12logger_entry",
+ "self_type" : "_ZTI12logger_entry",
+ "size" : 28,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "y",
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "field_name" : "cb",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "field_name" : "cr",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "field_name" : "ystride",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "field_name" : "cstride",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "field_name" : "chroma_step",
+ "field_offset" : 320,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "field_name" : "reserved",
+ "field_offset" : 384,
+ "referenced_type" : "_ZTIA8_j"
+ }
+ ],
+ "linker_set_key" : "_ZTI13android_ycbcr",
+ "name" : "android_ycbcr",
+ "referenced_type" : "_ZTI13android_ycbcr",
+ "self_type" : "_ZTI13android_ycbcr",
+ "size" : 80,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "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_outside_system/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "x",
+ "referenced_type" : "_ZTIf"
+ },
+ {
+ "field_name" : "y",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "linker_set_key" : "_ZTI16android_xy_color",
+ "name" : "android_xy_color",
+ "referenced_type" : "_ZTI16android_xy_color",
+ "self_type" : "_ZTI16android_xy_color",
+ "size" : 8,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "top_left",
+ "referenced_type" : "_ZTIPh"
+ },
+ {
+ "field_name" : "component",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTI22android_flex_component"
+ },
+ {
+ "field_name" : "bits_per_component",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "bits_used",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "h_increment",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "v_increment",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "h_subsampling",
+ "field_offset" : 224,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "v_subsampling",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTI18android_flex_plane",
+ "name" : "android_flex_plane",
+ "referenced_type" : "_ZTI18android_flex_plane",
+ "self_type" : "_ZTI18android_flex_plane",
+ "size" : 40,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "format",
+ "referenced_type" : "_ZTI19android_flex_format"
+ },
+ {
+ "field_name" : "num_planes",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "planes",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIP18android_flex_plane"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_flex_layout",
+ "name" : "android_flex_layout",
+ "referenced_type" : "_ZTI19android_flex_layout",
+ "self_type" : "_ZTI19android_flex_layout",
+ "size" : 16,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "num_points",
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "reserved",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIA8_j"
+ },
+ {
+ "field_name" : "xyzc_points",
+ "field_offset" : 288,
+ "referenced_type" : "_ZTIA_f"
+ }
+ ],
+ "linker_set_key" : "_ZTI20android_depth_points",
+ "name" : "android_depth_points",
+ "referenced_type" : "_ZTI20android_depth_points",
+ "self_type" : "_ZTI20android_depth_points",
+ "size" : 36,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "struct_size",
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "field_name" : "buffer_id",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "priority",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "tag",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "field_name" : "file",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "field_name" : "line",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "message",
+ "field_offset" : 320,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTI21__android_log_message",
+ "name" : "__android_log_message",
+ "referenced_type" : "_ZTI21__android_log_message",
+ "self_type" : "_ZTI21__android_log_message",
+ "size" : 48,
+ "source_file" : "system/logging/liblog/include_vndk/android/log.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "maxContentLightLevel",
+ "referenced_type" : "_ZTIf"
+ },
+ {
+ "field_name" : "maxFrameAverageLightLevel",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_cta861_3_metadata",
+ "name" : "android_cta861_3_metadata",
+ "referenced_type" : "_ZTI25android_cta861_3_metadata",
+ "self_type" : "_ZTI25android_cta861_3_metadata",
+ "size" : 8,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "displayPrimaryRed",
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "displayPrimaryGreen",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "displayPrimaryBlue",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "whitePoint",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "maxLuminance",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIf"
+ },
+ {
+ "field_name" : "minLuminance",
+ "field_offset" : 288,
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "linker_set_key" : "_ZTI26android_smpte2086_metadata",
+ "name" : "android_smpte2086_metadata",
+ "referenced_type" : "_ZTI26android_smpte2086_metadata",
+ "self_type" : "_ZTI26android_smpte2086_metadata",
+ "size" : 40,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "referenced_type" : "_ZTIN7log_msgUt_E"
+ }
+ ],
+ "linker_set_key" : "_ZTI7log_msg",
+ "name" : "log_msg",
+ "referenced_type" : "_ZTI7log_msg",
+ "self_type" : "_ZTI7log_msg",
+ "size" : 5124,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 1,
+ "fields" :
+ [
+ {
+ "field_name" : "tv_sec",
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "tv_nsec",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "linker_set_key" : "_ZTI8log_time",
+ "name" : "log_time",
+ "referenced_type" : "_ZTI8log_time",
+ "self_type" : "_ZTI8log_time",
+ "size" : 8,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_time.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLogTag",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPriority",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTI19android_LogPriority"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mIgnoreBlankLines",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android10LogPrinterE",
+ "name" : "android::LogPrinter",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android10LogPrinterE",
+ "self_type" : "_ZTIN7android10LogPrinterE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android10LogPrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android10LogPrinter9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10LogPrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10LogPrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mStorage",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mCount",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mFlags",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIKj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mItemSize",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIKm"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android10VectorImplE",
+ "name" : "android::VectorImpl",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIN7android10VectorImplE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android10VectorImplE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10VectorImplD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10VectorImplD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl12do_constructEPvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl10do_destroyEPvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl7do_copyEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl8do_splatEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl15do_move_forwardEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl16do_move_backwardEPvPKvm"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mTag",
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android11ScopedTraceE",
+ "name" : "android::ScopedTrace",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android11ScopedTraceE",
+ "self_type" : "_ZTIN7android11ScopedTraceE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Trace.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCount",
+ "referenced_type" : "_ZTINSt3__16atomicIiEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "android::LightRefBase<android::NativeHandle>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android12NativeHandleE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCount",
+ "referenced_type" : "_ZTINSt3__16atomicIiEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE",
+ "name" : "android::LightRefBase<android::VirtualLightRefBase>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE",
+ "self_type" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android19VirtualLightRefBaseE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mHandle",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mOwnsHandle",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android12NativeHandleE",
+ "name" : "android::NativeHandle",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android12NativeHandleE",
+ "self_type" : "_ZTIN7android12NativeHandleE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mPrinter",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIRN7android7PrinterE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13PrefixPrinterE",
+ "name" : "android::PrefixPrinter",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android13PrefixPrinterE",
+ "self_type" : "_ZTIN7android13PrefixPrinterE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android13PrefixPrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android13PrefixPrinter9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android13PrefixPrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android13PrefixPrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_pointer<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_pointer<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEEE",
+ "name" : "android::trait_pointer<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "is_virtual" : true,
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14LooperCallbackE",
+ "name" : "android::LooperCallback",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14LooperCallbackE",
+ "self_type" : "_ZTIN7android14LooperCallbackE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 8,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14LooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14LooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14LooperCallbackD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android14LooperCallback11handleEventEiiPv"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -8,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -8,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14LooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android14LooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android14LooperCallbackD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "is_virtual" : true,
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14MessageHandlerE",
+ "name" : "android::MessageHandler",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14MessageHandlerE",
+ "self_type" : "_ZTIN7android14MessageHandlerE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 8,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14MessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14MessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14MessageHandlerD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android14MessageHandler13handleMessageERKNS_7MessageE"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -8,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -8,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14MessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android14MessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android14MessageHandlerD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android14ReferenceMoverE",
+ "name" : "android::ReferenceMover",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14ReferenceMoverE",
+ "self_type" : "_ZTIN7android14ReferenceMoverE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android8String16E"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mData",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIKN7android8String1610StaticDataILm1EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14StaticString16ILm1EEE",
+ "name" : "android::StaticString16<1>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14StaticString16ILm1EEE",
+ "self_type" : "_ZTIN7android14StaticString16ILm1EEE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mTarget",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14String8PrinterE",
+ "name" : "android::String8Printer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14String8PrinterE",
+ "self_type" : "_ZTIN7android14String8PrinterE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14String8PrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android14String8Printer9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14String8PrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14String8PrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIN7android16ReferenceRenamerE",
+ "name" : "android::ReferenceRenamer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIN7android16ReferenceRenamerE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android16ReferenceRenamerE"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android16ReferenceRenamerclEm"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16SortedVectorImplE",
+ "name" : "android::SortedVectorImpl",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIN7android16SortedVectorImplE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android16SortedVectorImplE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android16SortedVectorImplD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android16SortedVectorImplD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl12do_constructEPvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl10do_destroyEPvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl7do_copyEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl8do_splatEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl15do_move_forwardEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl16do_move_backwardEPvPKvm"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android16SortedVectorImpl10do_compareEPKvS2_"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTINSt3__117integral_constantIbLb0EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16use_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::use_trivial_move<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android16use_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android16use_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTINSt3__117integral_constantIbLb0EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16use_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::use_trivial_move<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android16use_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android16use_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTINSt3__117integral_constantIbLb0EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16use_trivial_moveINS_6Looper8ResponseEEE",
+ "name" : "android::use_trivial_move<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android16use_trivial_moveINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android16use_trivial_moveINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android14MessageHandlerE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mHandler",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18WeakMessageHandlerE",
+ "name" : "android::WeakMessageHandler",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android18WeakMessageHandlerE",
+ "self_type" : "_ZTIN7android18WeakMessageHandlerE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 24,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android18WeakMessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android18WeakMessageHandler13handleMessageERKNS_7MessageE"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -24,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -24,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android18WeakMessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_copy<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_copy<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_copy<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIbEE",
+ "name" : "android::trait_trivial_copy<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIcEE",
+ "name" : "android::trait_trivial_copy<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIdEE",
+ "name" : "android::trait_trivial_copy<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIfEE",
+ "name" : "android::trait_trivial_copy<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIhEE",
+ "name" : "android::trait_trivial_copy<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIiEE",
+ "name" : "android::trait_trivial_copy<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIjEE",
+ "name" : "android::trait_trivial_copy<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIlEE",
+ "name" : "android::trait_trivial_copy<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyImEE",
+ "name" : "android::trait_trivial_copy<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIsEE",
+ "name" : "android::trait_trivial_copy<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyItEE",
+ "name" : "android::trait_trivial_copy<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIvEE",
+ "name" : "android::trait_trivial_copy<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIxEE",
+ "name" : "android::trait_trivial_copy<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIyEE",
+ "name" : "android::trait_trivial_copy<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_ctor<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_ctor<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_ctor<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIbEE",
+ "name" : "android::trait_trivial_ctor<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIcEE",
+ "name" : "android::trait_trivial_ctor<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIdEE",
+ "name" : "android::trait_trivial_ctor<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIfEE",
+ "name" : "android::trait_trivial_ctor<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIhEE",
+ "name" : "android::trait_trivial_ctor<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIiEE",
+ "name" : "android::trait_trivial_ctor<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIjEE",
+ "name" : "android::trait_trivial_ctor<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIlEE",
+ "name" : "android::trait_trivial_ctor<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorImEE",
+ "name" : "android::trait_trivial_ctor<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIsEE",
+ "name" : "android::trait_trivial_ctor<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorItEE",
+ "name" : "android::trait_trivial_ctor<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIvEE",
+ "name" : "android::trait_trivial_ctor<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIxEE",
+ "name" : "android::trait_trivial_ctor<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIyEE",
+ "name" : "android::trait_trivial_ctor<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_dtor<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_dtor<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_dtor<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIbEE",
+ "name" : "android::trait_trivial_dtor<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIcEE",
+ "name" : "android::trait_trivial_dtor<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIdEE",
+ "name" : "android::trait_trivial_dtor<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIfEE",
+ "name" : "android::trait_trivial_dtor<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIhEE",
+ "name" : "android::trait_trivial_dtor<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIiEE",
+ "name" : "android::trait_trivial_dtor<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIjEE",
+ "name" : "android::trait_trivial_dtor<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIlEE",
+ "name" : "android::trait_trivial_dtor<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorImEE",
+ "name" : "android::trait_trivial_dtor<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIsEE",
+ "name" : "android::trait_trivial_dtor<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorItEE",
+ "name" : "android::trait_trivial_dtor<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIvEE",
+ "name" : "android::trait_trivial_dtor<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIxEE",
+ "name" : "android::trait_trivial_dtor<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIyEE",
+ "name" : "android::trait_trivial_dtor<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_move<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_move<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_move<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_7String8EEE",
+ "name" : "android::trait_trivial_move<android::String8>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/String8.h",
+ "template_args" :
+ [
+ "_ZTIN7android7String8E"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_8String16EEE",
+ "name" : "android::trait_trivial_move<android::String16>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/String16.h",
+ "template_args" :
+ [
+ "_ZTIN7android8String16E"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIbEE",
+ "name" : "android::trait_trivial_move<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIcEE",
+ "name" : "android::trait_trivial_move<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIdEE",
+ "name" : "android::trait_trivial_move<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIfEE",
+ "name" : "android::trait_trivial_move<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIhEE",
+ "name" : "android::trait_trivial_move<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIiEE",
+ "name" : "android::trait_trivial_move<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIjEE",
+ "name" : "android::trait_trivial_move<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIlEE",
+ "name" : "android::trait_trivial_move<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveImEE",
+ "name" : "android::trait_trivial_move<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIsEE",
+ "name" : "android::trait_trivial_move<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveItEE",
+ "name" : "android::trait_trivial_move<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIvEE",
+ "name" : "android::trait_trivial_move<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIxEE",
+ "name" : "android::trait_trivial_move<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIyEE",
+ "name" : "android::trait_trivial_move<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android19VirtualLightRefBaseE",
+ "name" : "android::VirtualLightRefBase",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android19VirtualLightRefBaseE",
+ "self_type" : "_ZTIN7android19VirtualLightRefBaseE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android19VirtualLightRefBaseE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android19VirtualLightRefBaseD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android19VirtualLightRefBaseD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android14LooperCallbackE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCallback",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPFiiiPvE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android20SimpleLooperCallbackE",
+ "name" : "android::SimpleLooperCallback",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android20SimpleLooperCallbackE",
+ "self_type" : "_ZTIN7android20SimpleLooperCallbackE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 16,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android20SimpleLooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android20SimpleLooperCallback11handleEventEiiPv"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -16,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -16,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android20SimpleLooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "name" : "android::sp<android::NativeHandle>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "self_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android12NativeHandleE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "name" : "android::sp<android::LooperCallback>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android14LooperCallbackE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android14MessageHandlerE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android20SimpleLooperCallbackE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android6LooperE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android6ThreadE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "m_refs",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "name" : "android::wp<android::MessageHandler>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android14MessageHandlerE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "m_refs",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "name" : "android::wp<android::Thread>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android6ThreadE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "fd_",
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android4base11borrowed_fdE",
+ "name" : "android::base::borrowed_fd",
+ "referenced_type" : "_ZTIN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIN7android4base11borrowed_fdE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android4base13DefaultCloserE",
+ "name" : "android::base::DefaultCloser",
+ "referenced_type" : "_ZTIN7android4base13DefaultCloserE",
+ "self_type" : "_ZTIN7android4base13DefaultCloserE",
+ "size" : 1,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "fd_",
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "android::base::unique_fd_impl<android::base::DefaultCloser>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h",
+ "template_args" :
+ [
+ "_ZTIN7android4base13DefaultCloserE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "referenced_type" : "_ZTIRN7android5MutexE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android5Mutex8AutolockE",
+ "name" : "android::Mutex::Autolock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android5Mutex8AutolockE",
+ "self_type" : "_ZTIN7android5Mutex8AutolockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mMutex",
+ "referenced_type" : "_ZTI15pthread_mutex_t"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android5MutexE",
+ "name" : "android::Mutex",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android5MutexE",
+ "self_type" : "_ZTIN7android5MutexE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "access" : "private",
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "uptime",
+ "referenced_type" : "_ZTIl"
+ },
+ {
+ "field_name" : "handler",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "field_name" : "message",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIN7android7MessageE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "name" : "android::Looper::MessageEnvelope",
+ "referenced_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "fd",
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "ident",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "events",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "callback",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE"
+ },
+ {
+ "field_name" : "data",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper7RequestE",
+ "name" : "android::Looper::Request",
+ "referenced_type" : "_ZTIN7android6Looper7RequestE",
+ "self_type" : "_ZTIN7android6Looper7RequestE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "seq",
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "field_name" : "events",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "request",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIN7android6Looper7RequestE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper8ResponseE",
+ "name" : "android::Looper::Response",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIN7android6Looper8ResponseE",
+ "size" : 48,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mAllowNonCallbacks",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIKb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mWakeEventFd",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIN7android5MutexE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mMessageEnvelopes",
+ "field_offset" : 512,
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mSendingMessage",
+ "field_offset" : 832,
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPolling",
+ "field_offset" : 840,
+ "referenced_type" : "_ZTIVb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mEpollFd",
+ "field_offset" : 864,
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mEpollRebuildRequired",
+ "field_offset" : 896,
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mRequests",
+ "field_offset" : 960,
+ "referenced_type" : "_ZTINSt3__113unordered_mapImN7android6Looper7RequestENS_4hashImEENS_8equal_toImEENS_9allocatorINS_4pairIKmS3_EEEEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mSequenceNumberByFd",
+ "field_offset" : 1280,
+ "referenced_type" : "_ZTINSt3__113unordered_mapIimNS_4hashIiEENS_8equal_toIiEENS_9allocatorINS_4pairIKimEEEEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mNextRequestSeq",
+ "field_offset" : 1600,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mResponses",
+ "field_offset" : 1664,
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mResponseIndex",
+ "field_offset" : 1984,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mNextMessageUptime",
+ "field_offset" : 2048,
+ "referenced_type" : "_ZTIl"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6LooperE",
+ "name" : "android::Looper",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6LooperE",
+ "self_type" : "_ZTIN7android6LooperE",
+ "size" : 264,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6LooperE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6LooperD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6LooperD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "referenced_type" : "_ZTIRN7android6RWLockE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLock9AutoRLockE",
+ "name" : "android::RWLock::AutoRLock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoRLockE",
+ "self_type" : "_ZTIN7android6RWLock9AutoRLockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "referenced_type" : "_ZTIRN7android6RWLockE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLock9AutoWLockE",
+ "name" : "android::RWLock::AutoWLock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoWLockE",
+ "self_type" : "_ZTIN7android6RWLock9AutoWLockE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mRWLock",
+ "referenced_type" : "_ZTI16pthread_rwlock_t"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLockE",
+ "name" : "android::RWLock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6RWLockE",
+ "self_type" : "_ZTIN7android6RWLockE",
+ "size" : 56,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "is_virtual" : true,
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCanCallJava",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIKb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mThread",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIN7android5MutexE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mThreadExitedCondition",
+ "field_offset" : 512,
+ "referenced_type" : "_ZTIN7android9ConditionE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mStatus",
+ "field_offset" : 896,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mExitPending",
+ "field_offset" : 928,
+ "referenced_type" : "_ZTIVb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mRunning",
+ "field_offset" : 936,
+ "referenced_type" : "_ZTIVb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mHoldSelf",
+ "field_offset" : 960,
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mTid",
+ "field_offset" : 1024,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6ThreadE",
+ "name" : "android::Thread",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6ThreadE",
+ "self_type" : "_ZTIN7android6ThreadE",
+ "size" : 152,
+ "source_file" : "system/core/libutils/include/utils/Thread.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 136,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6ThreadE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6ThreadD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6ThreadD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android6Thread3runEPKcim"
+ },
+ {
+ "mangled_component_name" : "_ZN7android6Thread11requestExitEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android6Thread10readyToRunEv"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android6Thread10threadLoopEv"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -136,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -136,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6ThreadE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android6ThreadD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n24_N7android6ThreadD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::Vector<android::sysprop_change_callback_info>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_28sysprop_change_callback_infoEED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_28sysprop_change_callback_infoEED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE12do_constructEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE10do_destroyEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE7do_copyEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE8do_splatEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE15do_move_forwardEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE16do_move_backwardEPvPKvm"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::Vector<android::Looper::MessageEnvelope>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper15MessageEnvelopeEED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper15MessageEnvelopeEED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE12do_constructEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE10do_destroyEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE7do_copyEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE8do_splatEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE15do_move_forwardEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE16do_move_backwardEPvPKvm"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "android::Vector<android::Looper::Response>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper8ResponseEED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper8ResponseEED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE12do_constructEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE10do_destroyEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE7do_copyEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE8do_splatEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE15do_move_forwardEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE16do_move_backwardEPvPKvm"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_7String8EEE",
+ "name" : "android::Vector<android::String8>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android7String8E"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_7String8EEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_7String8EED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_7String8EED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE12do_constructEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE10do_destroyEPvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE7do_copyEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE8do_splatEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE15do_move_forwardEPvPKvm"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE16do_move_backwardEPvPKvm"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::traits<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::traits<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper8ResponseEEE",
+ "name" : "android::traits<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFileName",
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mBasePtr",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mBaseLength",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mDataOffset",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIl"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mDataPtr",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mDataLength",
+ "field_offset" : 320,
+ "referenced_type" : "_ZTIm"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7FileMapE",
+ "name" : "android::FileMap",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIN7android7FileMapE",
+ "size" : 48,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "what",
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7MessageE",
+ "name" : "android::Message",
+ "referenced_type" : "_ZTIN7android7MessageE",
+ "self_type" : "_ZTIN7android7MessageE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTIN7android7PrinterE",
+ "name" : "android::Printer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7PrinterE",
+ "self_type" : "_ZTIN7android7PrinterE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android7PrinterE"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android7Printer9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7PrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7PrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android7RefBase12weakref_typeE",
+ "name" : "android::RefBase::weakref_type",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mRefs",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIKPN7android7RefBase12weakref_implE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7RefBaseE",
+ "name" : "android::RefBase",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7RefBaseE",
+ "self_type" : "_ZTIN7android7RefBaseE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android7RefBaseE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7RefBaseD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7RefBaseD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mString",
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7String8E",
+ "name" : "android::String8",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIN7android7String8E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "size",
+ "referenced_type" : "_ZTIKj"
+ },
+ {
+ "field_name" : "data",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIA1_Ds"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android8String1610StaticDataILm1EEE",
+ "name" : "android::String16::StaticData<1>",
+ "referenced_type" : "_ZTIN7android8String1610StaticDataILm1EEE",
+ "self_type" : "_ZTIN7android8String1610StaticDataILm1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mString",
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android8String16E",
+ "name" : "android::String16",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIN7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android9CallStack12StackDeleterE",
+ "name" : "android::CallStack::StackDeleter",
+ "referenced_type" : "_ZTIN7android9CallStack12StackDeleterE",
+ "self_type" : "_ZTIN7android9CallStack12StackDeleterE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFrameLines",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9CallStackE",
+ "name" : "android::CallStack",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9CallStackE",
+ "self_type" : "_ZTIN7android9CallStackE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCond",
+ "referenced_type" : "_ZTI14pthread_cond_t"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9ConditionE",
+ "name" : "android::Condition",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9ConditionE",
+ "self_type" : "_ZTIN7android9ConditionE",
+ "size" : 48,
+ "source_file" : "system/core/libutils/include/utils/Condition.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFd",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mIndent",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mFormatString",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIA20_c"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9FdPrinterE",
+ "name" : "android::FdPrinter",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9FdPrinterE",
+ "self_type" : "_ZTIN7android9FdPrinterE",
+ "size" : 48,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android9FdPrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android9FdPrinter9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android9FdPrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android9FdPrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mName",
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mClock",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mStartTime",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIl"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9StopWatchE",
+ "name" : "android::StopWatch",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9StopWatchE",
+ "self_type" : "_ZTIN7android9StopWatchE",
+ "size" : 24,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFilename",
+ "referenced_type" : "_ZTIN7android7String8E"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mFileMap",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mBuffer",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mOwnBuffer",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLength",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIm"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mCurrent",
+ "field_offset" : 320,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLineNumber",
+ "field_offset" : 384,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9TokenizerE",
+ "name" : "android::Tokenizer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9TokenizerE",
+ "self_type" : "_ZTIN7android9TokenizerE",
+ "size" : 56,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "buf",
+ "referenced_type" : "_ZTIA5121_h"
+ },
+ {
+ "field_name" : "entry",
+ "referenced_type" : "_ZTI12logger_entry"
+ }
+ ],
+ "is_anonymous" : true,
+ "linker_set_key" : "_ZTIN7log_msgUt_E",
+ "name" : "log_msg::(anonymous)",
+ "record_kind" : "union",
+ "referenced_type" : "_ZTIN7log_msgUt_E",
+ "self_type" : "_ZTIN7log_msgUt_E",
+ "size" : 5124,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ }
+ ],
+ "rvalue_reference_types" :
+ [
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android2spINS_12NativeHandleEEE",
+ "name" : "android::sp<android::NativeHandle> &&",
+ "referenced_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "self_type" : "_ZTION7android2spINS_12NativeHandleEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler> &&",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTION7android2spINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback> &&",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTION7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper> &&",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTION7android2spINS_6LooperEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread> &&",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTION7android2spINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "android::base::unique_fd_impl<android::base::DefaultCloser> &&",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTION7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 8,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android7FileMapE",
+ "name" : "android::FileMap &&",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTION7android7FileMapE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "linker_set_key" : "_ZTION7android8String16E",
+ "name" : "android::String16 &&",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTION7android8String16E",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ }
+ ]
+}
diff --git a/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump b/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump
new file mode 100644
index 0000000..f88da15
--- /dev/null
+++ b/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump
@@ -0,0 +1,15549 @@
+{
+ "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_outside_system/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 2,
+ "linker_set_key" : "_ZTIA1_Ds",
+ "name" : "char16_t[1]",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIA1_Ds",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIA20_c",
+ "name" : "char[20]",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIA20_c",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIA5121_h",
+ "name" : "unsigned char[5121]",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIA5121_h",
+ "size" : 5121,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIA8_j",
+ "name" : "unsigned int[8]",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIA8_j",
+ "size" : 32,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "linker_set_key" : "_ZTIA_f",
+ "name" : "float[]",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIA_f",
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ }
+ ],
+ "builtin_types" :
+ [
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIDi",
+ "name" : "char32_t",
+ "referenced_type" : "_ZTIDi",
+ "self_type" : "_ZTIDi",
+ "size" : 4
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIDn",
+ "name" : "std::nullptr_t",
+ "referenced_type" : "_ZTIDn",
+ "self_type" : "_ZTIDn",
+ "size" : 4
+ },
+ {
+ "alignment" : 2,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIDs",
+ "name" : "char16_t",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIDs",
+ "size" : 2
+ },
+ {
+ "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" : 8,
+ "linker_set_key" : "_ZTId",
+ "name" : "double",
+ "referenced_type" : "_ZTId",
+ "self_type" : "_ZTId",
+ "size" : 8
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIf",
+ "name" : "float",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIf",
+ "size" : 4
+ },
+ {
+ "alignment" : 1,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIh",
+ "name" : "unsigned char",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIh",
+ "size" : 1
+ },
+ {
+ "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" : 4,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIl",
+ "name" : "long",
+ "referenced_type" : "_ZTIl",
+ "self_type" : "_ZTIl",
+ "size" : 4
+ },
+ {
+ "alignment" : 4,
+ "is_integral" : true,
+ "is_unsigned" : true,
+ "linker_set_key" : "_ZTIm",
+ "name" : "unsigned long",
+ "referenced_type" : "_ZTIm",
+ "self_type" : "_ZTIm",
+ "size" : 4
+ },
+ {
+ "alignment" : 2,
+ "is_integral" : true,
+ "linker_set_key" : "_ZTIs",
+ "name" : "short",
+ "referenced_type" : "_ZTIs",
+ "self_type" : "_ZTIs",
+ "size" : 2
+ },
+ {
+ "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" : "_Z24androidCreateThreadGetIDPFiPvES_PS_"
+ },
+ {
+ "name" : "_ZN7android10LogPrinter8printRawEPKc"
+ },
+ {
+ "name" : "_ZN7android10LogPrinter9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android10LogPrinterC1EPKc19android_LogPriorityS2_b"
+ },
+ {
+ "name" : "_ZN7android10LogPrinterC2EPKc19android_LogPriorityS2_b"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl11appendArrayEPKvj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl11setCapacityEj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl12appendVectorERKS0_"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13editArrayImplEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13finish_vectorEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13insertArrayAtEPKvjj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl13removeItemsAtEjj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl14insertVectorAtERKS0_j"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl15release_storageEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl16editItemLocationEj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl3addEPKv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl3addEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl3popEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4pushEPKv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4pushEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4sortEPFiPKvS2_E"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl4sortEPFiPKvS2_PvES3_"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl5_growEjj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl5clearEv"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl6resizeEj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl7_shrinkEjj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl8insertAtEPKvjj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl8insertAtEjj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl9replaceAtEPKvj"
+ },
+ {
+ "name" : "_ZN7android10VectorImpl9replaceAtEj"
+ },
+ {
+ "name" : "_ZN7android10VectorImplC2ERKS0_"
+ },
+ {
+ "name" : "_ZN7android10VectorImplC2Ejj"
+ },
+ {
+ "name" : "_ZN7android10VectorImplD0Ev"
+ },
+ {
+ "name" : "_ZN7android10VectorImplD1Ev"
+ },
+ {
+ "name" : "_ZN7android10VectorImplD2Ev"
+ },
+ {
+ "name" : "_ZN7android10VectorImplaSERKS0_"
+ },
+ {
+ "name" : "_ZN7android11uptimeNanosEv"
+ },
+ {
+ "name" : "_ZN7android12NativeHandle6createEP13native_handleb"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleC1EP13native_handleb"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleC2EP13native_handleb"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleD1Ev"
+ },
+ {
+ "name" : "_ZN7android12NativeHandleD2Ev"
+ },
+ {
+ "name" : "_ZN7android12SharedBuffer5allocEj"
+ },
+ {
+ "name" : "_ZN7android12SharedBuffer7deallocEPKS0_"
+ },
+ {
+ "name" : "_ZN7android12uptimeMillisEv"
+ },
+ {
+ "name" : "_ZN7android13PrefixPrinter9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android13PrefixPrinterC1ERNS_7PrinterEPKc"
+ },
+ {
+ "name" : "_ZN7android13PrefixPrinterC2ERNS_7PrinterEPKc"
+ },
+ {
+ "name" : "_ZN7android14LooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZN7android14LooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZN7android14LooperCallbackD2Ev"
+ },
+ {
+ "name" : "_ZN7android14MessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZN7android14MessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZN7android14MessageHandlerD2Ev"
+ },
+ {
+ "name" : "_ZN7android14String8Printer9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android14String8PrinterC1EPNS_7String8EPKc"
+ },
+ {
+ "name" : "_ZN7android14String8PrinterC2EPNS_7String8EPKc"
+ },
+ {
+ "name" : "_ZN7android14sp_report_raceEv"
+ },
+ {
+ "name" : "_ZN7android14statusToStringEi"
+ },
+ {
+ "name" : "_ZN7android15elapsedRealtimeEv"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl3addEPKv"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl5mergeERKNS_10VectorImplE"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl5mergeERKS0_"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImpl6removeEPKv"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplC2ERKNS_10VectorImplE"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplC2Ejj"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplD0Ev"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplD1Ev"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplD2Ev"
+ },
+ {
+ "name" : "_ZN7android16SortedVectorImplaSERKS0_"
+ },
+ {
+ "name" : "_ZN7android17JenkinsHashWhitenEj"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandler13handleMessageERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerC1ERKNS_2wpINS_14MessageHandlerEEE"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerC2ERKNS_2wpINS_14MessageHandlerEEE"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZN7android18WeakMessageHandlerD2Ev"
+ },
+ {
+ "name" : "_ZN7android19JenkinsHashMixBytesEjPKhj"
+ },
+ {
+ "name" : "_ZN7android19elapsedRealtimeNanoEv"
+ },
+ {
+ "name" : "_ZN7android20JenkinsHashMixShortsEjPKtj"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallback11handleEventEiiPv"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackC1EPFiiiPvE"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackC2EPFiiiPvE"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZN7android20SimpleLooperCallbackD2Ev"
+ },
+ {
+ "name" : "_ZN7android21report_sysprop_changeEv"
+ },
+ {
+ "name" : "_ZN7android23sp_report_stack_pointerEv"
+ },
+ {
+ "name" : "_ZN7android27add_sysprop_change_callbackEPFvvEi"
+ },
+ {
+ "name" : "_ZN7android30get_report_sysprop_change_funcEv"
+ },
+ {
+ "name" : "_ZN7android47LightRefBase_reportIncStrongRequireStrongFailedEPKv"
+ },
+ {
+ "name" : "_ZN7android6Looper10initTLSKeyEv"
+ },
+ {
+ "name" : "_ZN7android6Looper11sendMessageERKNS_2spINS_14MessageHandlerEEERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android6Looper12getForThreadEv"
+ },
+ {
+ "name" : "_ZN7android6Looper12setForThreadERKNS_2spIS0_EE"
+ },
+ {
+ "name" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEE"
+ },
+ {
+ "name" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEEi"
+ },
+ {
+ "name" : "_ZN7android6Looper16threadDestructorEPv"
+ },
+ {
+ "name" : "_ZN7android6Looper17sendMessageAtTimeExRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android6Looper18rebuildEpollLockedEv"
+ },
+ {
+ "name" : "_ZN7android6Looper18sendMessageDelayedExRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE"
+ },
+ {
+ "name" : "_ZN7android6Looper26removeSequenceNumberLockedEy"
+ },
+ {
+ "name" : "_ZN7android6Looper26scheduleEpollRebuildLockedEv"
+ },
+ {
+ "name" : "_ZN7android6Looper4wakeEv"
+ },
+ {
+ "name" : "_ZN7android6Looper5addFdEiiiPFiiiPvES1_"
+ },
+ {
+ "name" : "_ZN7android6Looper5addFdEiiiRKNS_2spINS_14LooperCallbackEEEPv"
+ },
+ {
+ "name" : "_ZN7android6Looper6awokenEv"
+ },
+ {
+ "name" : "_ZN7android6Looper7pollAllEiPiS1_PPv"
+ },
+ {
+ "name" : "_ZN7android6Looper7prepareEi"
+ },
+ {
+ "name" : "_ZN7android6Looper8pollOnceEiPiS1_PPv"
+ },
+ {
+ "name" : "_ZN7android6Looper8removeFdEi"
+ },
+ {
+ "name" : "_ZN7android6Looper9pollInnerEi"
+ },
+ {
+ "name" : "_ZN7android6LooperC1Eb"
+ },
+ {
+ "name" : "_ZN7android6LooperC2Eb"
+ },
+ {
+ "name" : "_ZN7android6LooperD0Ev"
+ },
+ {
+ "name" : "_ZN7android6LooperD1Ev"
+ },
+ {
+ "name" : "_ZN7android6LooperD2Ev"
+ },
+ {
+ "name" : "_ZN7android6Thread10readyToRunEv"
+ },
+ {
+ "name" : "_ZN7android6Thread11_threadLoopEPv"
+ },
+ {
+ "name" : "_ZN7android6Thread11requestExitEv"
+ },
+ {
+ "name" : "_ZN7android6Thread18requestExitAndWaitEv"
+ },
+ {
+ "name" : "_ZN7android6Thread3runEPKcij"
+ },
+ {
+ "name" : "_ZN7android6Thread4joinEv"
+ },
+ {
+ "name" : "_ZN7android6ThreadC2Eb"
+ },
+ {
+ "name" : "_ZN7android6ThreadD0Ev"
+ },
+ {
+ "name" : "_ZN7android6ThreadD1Ev"
+ },
+ {
+ "name" : "_ZN7android6ThreadD2Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMap6adviseENS0_9MapAdviceE"
+ },
+ {
+ "name" : "_ZN7android7FileMap6createEPKcixjb"
+ },
+ {
+ "name" : "_ZN7android7FileMapC1EOS0_"
+ },
+ {
+ "name" : "_ZN7android7FileMapC1Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapC2EOS0_"
+ },
+ {
+ "name" : "_ZN7android7FileMapC2Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapD1Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapD2Ev"
+ },
+ {
+ "name" : "_ZN7android7FileMapaSEOS0_"
+ },
+ {
+ "name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "name" : "_ZN7android7PrinterC2Ev"
+ },
+ {
+ "name" : "_ZN7android7PrinterD0Ev"
+ },
+ {
+ "name" : "_ZN7android7PrinterD1Ev"
+ },
+ {
+ "name" : "_ZN7android7PrinterD2Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "name" : "_ZN7android7RefBase10renameRefsEjRKNS_16ReferenceRenamerE"
+ },
+ {
+ "name" : "_ZN7android7RefBase11renameRefIdEPNS0_12weakref_typeEPKvS4_"
+ },
+ {
+ "name" : "_ZN7android7RefBase11renameRefIdEPS0_PKvS3_"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type14attemptIncWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type16attemptIncStrongEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type18incWeakRequireWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type7decWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type7incWeakEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase12weakref_type7trackMeEbb"
+ },
+ {
+ "name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBase20extendObjectLifetimeEi"
+ },
+ {
+ "name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "name" : "_ZN7android7RefBaseC1Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseC2Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseD0Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseD1Ev"
+ },
+ {
+ "name" : "_ZN7android7RefBaseD2Ev"
+ },
+ {
+ "name" : "_ZN7android7String810appendPathEPKc"
+ },
+ {
+ "name" : "_ZN7android7String810lockBufferEj"
+ },
+ {
+ "name" : "_ZN7android7String811real_appendEPKcj"
+ },
+ {
+ "name" : "_ZN7android7String812appendFormatEPKcz"
+ },
+ {
+ "name" : "_ZN7android7String812unlockBufferEj"
+ },
+ {
+ "name" : "_ZN7android7String812unlockBufferEv"
+ },
+ {
+ "name" : "_ZN7android7String813appendFormatVEPKcSt9__va_list"
+ },
+ {
+ "name" : "_ZN7android7String816convertToResPathEv"
+ },
+ {
+ "name" : "_ZN7android7String85clearEv"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKDij"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKDsj"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKc"
+ },
+ {
+ "name" : "_ZN7android7String85setToEPKcj"
+ },
+ {
+ "name" : "_ZN7android7String85setToERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String86appendEPKc"
+ },
+ {
+ "name" : "_ZN7android7String86appendEPKcj"
+ },
+ {
+ "name" : "_ZN7android7String86appendERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String86formatEPKcz"
+ },
+ {
+ "name" : "_ZN7android7String87formatVEPKcSt9__va_list"
+ },
+ {
+ "name" : "_ZN7android7String87toLowerEv"
+ },
+ {
+ "name" : "_ZN7android7String89removeAllEPKc"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDi"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDij"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDs"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKDsj"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKc"
+ },
+ {
+ "name" : "_ZN7android7String8C1EPKcj"
+ },
+ {
+ "name" : "_ZN7android7String8C1ERKNS_8String16E"
+ },
+ {
+ "name" : "_ZN7android7String8C1ERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String8C1Ev"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDi"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDij"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDs"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKDsj"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKc"
+ },
+ {
+ "name" : "_ZN7android7String8C2EPKcj"
+ },
+ {
+ "name" : "_ZN7android7String8C2ERKNS_8String16E"
+ },
+ {
+ "name" : "_ZN7android7String8C2ERKS0_"
+ },
+ {
+ "name" : "_ZN7android7String8C2Ev"
+ },
+ {
+ "name" : "_ZN7android7String8D1Ev"
+ },
+ {
+ "name" : "_ZN7android7String8D2Ev"
+ },
+ {
+ "name" : "_ZN7android8String1610editResizeEj"
+ },
+ {
+ "name" : "_ZN7android8String1610replaceAllEDsDs"
+ },
+ {
+ "name" : "_ZN7android8String1613allocFromUTF8EPKcj"
+ },
+ {
+ "name" : "_ZN7android8String1614allocFromUTF16EPKDsj"
+ },
+ {
+ "name" : "_ZN7android8String164editEv"
+ },
+ {
+ "name" : "_ZN7android8String165allocEj"
+ },
+ {
+ "name" : "_ZN7android8String165setToEPKDs"
+ },
+ {
+ "name" : "_ZN7android8String165setToEPKDsj"
+ },
+ {
+ "name" : "_ZN7android8String165setToERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String165setToERKS0_jj"
+ },
+ {
+ "name" : "_ZN7android8String166appendEPKDsj"
+ },
+ {
+ "name" : "_ZN7android8String166appendERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String166insertEjPKDs"
+ },
+ {
+ "name" : "_ZN7android8String166insertEjPKDsj"
+ },
+ {
+ "name" : "_ZN7android8String167acquireEv"
+ },
+ {
+ "name" : "_ZN7android8String167releaseEv"
+ },
+ {
+ "name" : "_ZN7android8String16C1EOS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKDs"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKDsj"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKc"
+ },
+ {
+ "name" : "_ZN7android8String16C1EPKcj"
+ },
+ {
+ "name" : "_ZN7android8String16C1ERKNS_7String8E"
+ },
+ {
+ "name" : "_ZN7android8String16C1ERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C1ERKS0_jj"
+ },
+ {
+ "name" : "_ZN7android8String16C1Ev"
+ },
+ {
+ "name" : "_ZN7android8String16C2EOS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKDs"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKDsj"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKc"
+ },
+ {
+ "name" : "_ZN7android8String16C2EPKcj"
+ },
+ {
+ "name" : "_ZN7android8String16C2ERKNS_7String8E"
+ },
+ {
+ "name" : "_ZN7android8String16C2ERKS0_"
+ },
+ {
+ "name" : "_ZN7android8String16C2ERKS0_jj"
+ },
+ {
+ "name" : "_ZN7android8String16C2Ev"
+ },
+ {
+ "name" : "_ZN7android8String16D1Ev"
+ },
+ {
+ "name" : "_ZN7android8String16D2Ev"
+ },
+ {
+ "name" : "_ZN7android8String16aSEOS0_"
+ },
+ {
+ "name" : "_ZN7android9FdPrinter9printLineEPKc"
+ },
+ {
+ "name" : "_ZN7android9FdPrinterC1EijPKc"
+ },
+ {
+ "name" : "_ZN7android9FdPrinterC2EijPKc"
+ },
+ {
+ "name" : "_ZN7android9StopWatch5resetEv"
+ },
+ {
+ "name" : "_ZN7android9StopWatchC1EPKci"
+ },
+ {
+ "name" : "_ZN7android9StopWatchC2EPKci"
+ },
+ {
+ "name" : "_ZN7android9StopWatchD1Ev"
+ },
+ {
+ "name" : "_ZN7android9StopWatchD2Ev"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer12fromContentsERKNS_7String8EPKcPPS0_"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer14skipDelimitersEPKc"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer4openERKNS_7String8EPPS0_"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer8nextLineEv"
+ },
+ {
+ "name" : "_ZN7android9Tokenizer9nextTokenEPKc"
+ },
+ {
+ "name" : "_ZN7android9TokenizerC1ERKNS_7String8EPNS_7FileMapEPcbj"
+ },
+ {
+ "name" : "_ZN7android9TokenizerC2ERKNS_7String8EPNS_7FileMapEPcbj"
+ },
+ {
+ "name" : "_ZN7android9TokenizerD1Ev"
+ },
+ {
+ "name" : "_ZN7android9TokenizerD2Ev"
+ },
+ {
+ "name" : "_ZNK7android10VectorImpl12itemLocationEj"
+ },
+ {
+ "name" : "_ZNK7android10VectorImpl8capacityEv"
+ },
+ {
+ "name" : "_ZNK7android10VectorImpl8itemSizeEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer10editResizeEj"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer11attemptEditEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer4editEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer5resetEj"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer7acquireEv"
+ },
+ {
+ "name" : "_ZNK7android12SharedBuffer7releaseEj"
+ },
+ {
+ "name" : "_ZNK7android16SortedVectorImpl13_indexOrderOfEPKvPj"
+ },
+ {
+ "name" : "_ZNK7android16SortedVectorImpl7indexOfEPKv"
+ },
+ {
+ "name" : "_ZNK7android16SortedVectorImpl7orderOfEPKv"
+ },
+ {
+ "name" : "_ZNK7android6Looper20getAllowNonCallbacksEv"
+ },
+ {
+ "name" : "_ZNK7android6Looper7Request14getEpollEventsEv"
+ },
+ {
+ "name" : "_ZNK7android6Looper9isPollingEv"
+ },
+ {
+ "name" : "_ZNK7android6Thread11exitPendingEv"
+ },
+ {
+ "name" : "_ZNK7android6Thread6getTidEv"
+ },
+ {
+ "name" : "_ZNK7android6Thread9isRunningEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE10do_destroyEPvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE12do_constructEPvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE15do_move_forwardEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE16do_move_backwardEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE7do_copyEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE8do_splatEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE10do_destroyEPvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE12do_constructEPvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE15do_move_forwardEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE16do_move_backwardEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE7do_copyEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE8do_splatEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE10do_destroyEPvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE12do_constructEPvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE15do_move_forwardEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE16do_move_backwardEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE7do_copyEPvPKvj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNK7android6VectorINS_6Looper8ResponseEE8do_splatEPvPKvj"
+ },
+ {
+ "name" : "_ZNK7android7RefBase10createWeakEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase11getWeakRefsEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase12weakref_type12getWeakCountEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase12weakref_type7refBaseEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase12weakref_type9printRefsEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase14forceIncStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase14getStrongCountEv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase22incStrongRequireStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase9decStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7RefBase9incStrongEPKv"
+ },
+ {
+ "name" : "_ZNK7android7String810getPathDirEv"
+ },
+ {
+ "name" : "_ZNK7android7String811getBasePathEv"
+ },
+ {
+ "name" : "_ZNK7android7String811getPathLeafEv"
+ },
+ {
+ "name" : "_ZNK7android7String814find_extensionEv"
+ },
+ {
+ "name" : "_ZNK7android7String816getPathExtensionEv"
+ },
+ {
+ "name" : "_ZNK7android7String84findEPKcj"
+ },
+ {
+ "name" : "_ZNK7android7String86lengthEv"
+ },
+ {
+ "name" : "_ZNK7android7String88walkPathEPS0_"
+ },
+ {
+ "name" : "_ZNK7android8String1610startsWithEPKDs"
+ },
+ {
+ "name" : "_ZNK7android8String1610startsWithERKS0_"
+ },
+ {
+ "name" : "_ZNK7android8String1614isStaticStringEv"
+ },
+ {
+ "name" : "_ZNK7android8String1616staticStringSizeEv"
+ },
+ {
+ "name" : "_ZNK7android8String164sizeEv"
+ },
+ {
+ "name" : "_ZNK7android8String168containsEPKDs"
+ },
+ {
+ "name" : "_ZNK7android8String168findLastEDs"
+ },
+ {
+ "name" : "_ZNK7android8String169findFirstEDs"
+ },
+ {
+ "name" : "_ZNK7android9StopWatch11elapsedTimeEv"
+ },
+ {
+ "name" : "_ZNK7android9StopWatch4nameEv"
+ },
+ {
+ "name" : "_ZNK7android9Tokenizer11getLocationEv"
+ },
+ {
+ "name" : "_ZNK7android9Tokenizer19peekRemainderOfLineEv"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIiyEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE14__erase_uniqueIiEEjRKT_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIiyEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE25__emplace_unique_key_argsIiJRiRKyEEENS_4pairINS_15__hash_iteratorIPNS_11__hash_nodeIS2_PvEEEEbEERKT_DpOT0_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIiyEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE6rehashEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIiyEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE6removeENS_21__hash_const_iteratorIPNS_11__hash_nodeIS2_PvEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIiyEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE8__rehashEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIyN7android6Looper7RequestEEENS_22__unordered_map_hasherIyS5_NS_4hashIyEELb1EEENS_21__unordered_map_equalIyS5_NS_8equal_toIyEELb1EEENS_9allocatorIS5_EEE25__emplace_unique_key_argsIyJRKyRS4_EEENS_4pairINS_15__hash_iteratorIPNS_11__hash_nodeIS5_PvEEEEbEERKT_DpOT0_"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIyN7android6Looper7RequestEEENS_22__unordered_map_hasherIyS5_NS_4hashIyEELb1EEENS_21__unordered_map_equalIyS5_NS_8equal_toIyEELb1EEENS_9allocatorIS5_EEE6rehashEj"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIyN7android6Looper7RequestEEENS_22__unordered_map_hasherIyS5_NS_4hashIyEELb1EEENS_21__unordered_map_equalIyS5_NS_8equal_toIyEELb1EEENS_9allocatorIS5_EEE6removeENS_21__hash_const_iteratorIPNS_11__hash_nodeIS5_PvEEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZNSt3__112__hash_tableINS_17__hash_value_typeIyN7android6Looper7RequestEEENS_22__unordered_map_hasherIyS5_NS_4hashIyEELb1EEENS_21__unordered_map_equalIyS5_NS_8equal_toIyEELb1EEENS_9allocatorIS5_EEE8__rehashEj"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android14LooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android14LooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android14MessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android14MessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android6ThreadD0Ev"
+ },
+ {
+ "name" : "_ZTv0_n12_N7android6ThreadD1Ev"
+ },
+ {
+ "name" : "androidCreateRawThreadEtc"
+ },
+ {
+ "name" : "androidCreateThread"
+ },
+ {
+ "name" : "androidCreateThreadEtc"
+ },
+ {
+ "name" : "androidGetThreadId"
+ },
+ {
+ "name" : "androidGetThreadPriority"
+ },
+ {
+ "name" : "androidSetCreateThreadFunc"
+ },
+ {
+ "name" : "androidSetThreadName"
+ },
+ {
+ "name" : "androidSetThreadPriority"
+ },
+ {
+ "name" : "do_report_sysprop_change"
+ },
+ {
+ "name" : "strcmp16"
+ },
+ {
+ "name" : "strlen16"
+ },
+ {
+ "name" : "strncmp16"
+ },
+ {
+ "name" : "strnlen16"
+ },
+ {
+ "name" : "strstr16"
+ },
+ {
+ "name" : "strzcmp16"
+ },
+ {
+ "name" : "systemTime"
+ },
+ {
+ "name" : "toMillisecondTimeoutDelay"
+ },
+ {
+ "name" : "utf16_to_utf8"
+ },
+ {
+ "name" : "utf16_to_utf8_length"
+ },
+ {
+ "name" : "utf32_from_utf8_at"
+ },
+ {
+ "name" : "utf32_to_utf8"
+ },
+ {
+ "name" : "utf32_to_utf8_length"
+ },
+ {
+ "name" : "utf8_to_utf16"
+ },
+ {
+ "name" : "utf8_to_utf16_length"
+ },
+ {
+ "name" : "utf8_to_utf16_no_null_terminator"
+ }
+ ],
+ "elf_objects" :
+ [
+ {
+ "name" : "_ZN7android7FileMap9mPageSizeE"
+ },
+ {
+ "name" : "_ZTCN7android18WeakMessageHandlerE0_NS_14MessageHandlerE"
+ },
+ {
+ "name" : "_ZTCN7android20SimpleLooperCallbackE0_NS_14LooperCallbackE"
+ },
+ {
+ "name" : "_ZTTN7android14LooperCallbackE"
+ },
+ {
+ "name" : "_ZTTN7android14MessageHandlerE"
+ },
+ {
+ "name" : "_ZTTN7android18WeakMessageHandlerE"
+ },
+ {
+ "name" : "_ZTTN7android20SimpleLooperCallbackE"
+ },
+ {
+ "name" : "_ZTTN7android6ThreadE"
+ },
+ {
+ "name" : "_ZTVN7android10LogPrinterE"
+ },
+ {
+ "name" : "_ZTVN7android10VectorImplE"
+ },
+ {
+ "name" : "_ZTVN7android13PrefixPrinterE"
+ },
+ {
+ "name" : "_ZTVN7android14LooperCallbackE"
+ },
+ {
+ "name" : "_ZTVN7android14MessageHandlerE"
+ },
+ {
+ "name" : "_ZTVN7android14String8PrinterE"
+ },
+ {
+ "name" : "_ZTVN7android16SortedVectorImplE"
+ },
+ {
+ "name" : "_ZTVN7android18WeakMessageHandlerE"
+ },
+ {
+ "name" : "_ZTVN7android20SimpleLooperCallbackE"
+ },
+ {
+ "name" : "_ZTVN7android6LooperE"
+ },
+ {
+ "name" : "_ZTVN7android6ThreadE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "binding" : "weak",
+ "name" : "_ZTVN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "name" : "_ZTVN7android7PrinterE"
+ },
+ {
+ "name" : "_ZTVN7android7RefBaseE"
+ },
+ {
+ "name" : "_ZTVN7android9FdPrinterE"
+ }
+ ],
+ "enum_types" :
+ [
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : -1,
+ "name" : "SP_DEFAULT"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "SP_BACKGROUND"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "SP_FOREGROUND"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "SP_SYSTEM"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "SP_AUDIO_APP"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "SP_AUDIO_SYS"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "SP_TOP_APP"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "SP_RT_APP"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "SP_RESTRICTED"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "SP_CNT"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "SP_MAX"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "SP_SYSTEM_DEFAULT"
+ }
+ ],
+ "linker_set_key" : "_ZTI11SchedPolicy",
+ "name" : "SchedPolicy",
+ "referenced_type" : "_ZTI11SchedPolicy",
+ "self_type" : "_ZTI11SchedPolicy",
+ "size" : 4,
+ "source_file" : "system/core/libprocessgroup/include/processgroup/sched_policy.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_HDR_DOLBY_VISION"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_HDR_HDR10"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_HDR_HLG"
+ }
+ ],
+ "linker_set_key" : "_ZTI13android_hdr_t",
+ "name" : "android_hdr_t",
+ "referenced_type" : "_ZTI13android_hdr_t",
+ "self_type" : "_ZTI13android_hdr_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_HDR_HDR10_PLUS"
+ }
+ ],
+ "linker_set_key" : "_ZTI18android_hdr_v1_2_t",
+ "name" : "android_hdr_v1_2_t",
+ "referenced_type" : "_ZTI18android_hdr_v1_2_t",
+ "self_type" : "_ZTI18android_hdr_v1_2_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.2.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "ANDROID_LOG_UNKNOWN"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "ANDROID_LOG_DEFAULT"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "ANDROID_LOG_VERBOSE"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "ANDROID_LOG_DEBUG"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "ANDROID_LOG_INFO"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "ANDROID_LOG_WARN"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "ANDROID_LOG_ERROR"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "ANDROID_LOG_FATAL"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "ANDROID_LOG_SILENT"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_LogPriority",
+ "name" : "android_LogPriority",
+ "referenced_type" : "_ZTI19android_LogPriority",
+ "self_type" : "_ZTI19android_LogPriority",
+ "size" : 4,
+ "source_file" : "system/logging/liblog/include_vndk/android/log.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_UNKNOWN"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_DATASPACE_ARBITRARY"
+ },
+ {
+ "enum_field_value" : 16,
+ "name" : "HAL_DATASPACE_STANDARD_SHIFT"
+ },
+ {
+ "enum_field_value" : 4128768,
+ "name" : "HAL_DATASPACE_STANDARD_MASK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_STANDARD_UNSPECIFIED"
+ },
+ {
+ "enum_field_value" : 65536,
+ "name" : "HAL_DATASPACE_STANDARD_BT709"
+ },
+ {
+ "enum_field_value" : 131072,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_625"
+ },
+ {
+ "enum_field_value" : 196608,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 262144,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_525"
+ },
+ {
+ "enum_field_value" : 327680,
+ "name" : "HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 393216,
+ "name" : "HAL_DATASPACE_STANDARD_BT2020"
+ },
+ {
+ "enum_field_value" : 458752,
+ "name" : "HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE"
+ },
+ {
+ "enum_field_value" : 524288,
+ "name" : "HAL_DATASPACE_STANDARD_BT470M"
+ },
+ {
+ "enum_field_value" : 589824,
+ "name" : "HAL_DATASPACE_STANDARD_FILM"
+ },
+ {
+ "enum_field_value" : 655360,
+ "name" : "HAL_DATASPACE_STANDARD_DCI_P3"
+ },
+ {
+ "enum_field_value" : 720896,
+ "name" : "HAL_DATASPACE_STANDARD_ADOBE_RGB"
+ },
+ {
+ "enum_field_value" : 22,
+ "name" : "HAL_DATASPACE_TRANSFER_SHIFT"
+ },
+ {
+ "enum_field_value" : 130023424,
+ "name" : "HAL_DATASPACE_TRANSFER_MASK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_TRANSFER_UNSPECIFIED"
+ },
+ {
+ "enum_field_value" : 4194304,
+ "name" : "HAL_DATASPACE_TRANSFER_LINEAR"
+ },
+ {
+ "enum_field_value" : 8388608,
+ "name" : "HAL_DATASPACE_TRANSFER_SRGB"
+ },
+ {
+ "enum_field_value" : 12582912,
+ "name" : "HAL_DATASPACE_TRANSFER_SMPTE_170M"
+ },
+ {
+ "enum_field_value" : 16777216,
+ "name" : "HAL_DATASPACE_TRANSFER_GAMMA2_2"
+ },
+ {
+ "enum_field_value" : 20971520,
+ "name" : "HAL_DATASPACE_TRANSFER_GAMMA2_6"
+ },
+ {
+ "enum_field_value" : 25165824,
+ "name" : "HAL_DATASPACE_TRANSFER_GAMMA2_8"
+ },
+ {
+ "enum_field_value" : 29360128,
+ "name" : "HAL_DATASPACE_TRANSFER_ST2084"
+ },
+ {
+ "enum_field_value" : 33554432,
+ "name" : "HAL_DATASPACE_TRANSFER_HLG"
+ },
+ {
+ "enum_field_value" : 27,
+ "name" : "HAL_DATASPACE_RANGE_SHIFT"
+ },
+ {
+ "enum_field_value" : 939524096,
+ "name" : "HAL_DATASPACE_RANGE_MASK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_DATASPACE_RANGE_UNSPECIFIED"
+ },
+ {
+ "enum_field_value" : 134217728,
+ "name" : "HAL_DATASPACE_RANGE_FULL"
+ },
+ {
+ "enum_field_value" : 268435456,
+ "name" : "HAL_DATASPACE_RANGE_LIMITED"
+ },
+ {
+ "enum_field_value" : 402653184,
+ "name" : "HAL_DATASPACE_RANGE_EXTENDED"
+ },
+ {
+ "enum_field_value" : 512,
+ "name" : "HAL_DATASPACE_SRGB_LINEAR"
+ },
+ {
+ "enum_field_value" : 138477568,
+ "name" : "HAL_DATASPACE_V0_SRGB_LINEAR"
+ },
+ {
+ "enum_field_value" : 406913024,
+ "name" : "HAL_DATASPACE_V0_SCRGB_LINEAR"
+ },
+ {
+ "enum_field_value" : 513,
+ "name" : "HAL_DATASPACE_SRGB"
+ },
+ {
+ "enum_field_value" : 142671872,
+ "name" : "HAL_DATASPACE_V0_SRGB"
+ },
+ {
+ "enum_field_value" : 411107328,
+ "name" : "HAL_DATASPACE_V0_SCRGB"
+ },
+ {
+ "enum_field_value" : 257,
+ "name" : "HAL_DATASPACE_JFIF"
+ },
+ {
+ "enum_field_value" : 146931712,
+ "name" : "HAL_DATASPACE_V0_JFIF"
+ },
+ {
+ "enum_field_value" : 258,
+ "name" : "HAL_DATASPACE_BT601_625"
+ },
+ {
+ "enum_field_value" : 281149440,
+ "name" : "HAL_DATASPACE_V0_BT601_625"
+ },
+ {
+ "enum_field_value" : 259,
+ "name" : "HAL_DATASPACE_BT601_525"
+ },
+ {
+ "enum_field_value" : 281280512,
+ "name" : "HAL_DATASPACE_V0_BT601_525"
+ },
+ {
+ "enum_field_value" : 260,
+ "name" : "HAL_DATASPACE_BT709"
+ },
+ {
+ "enum_field_value" : 281083904,
+ "name" : "HAL_DATASPACE_V0_BT709"
+ },
+ {
+ "enum_field_value" : 139067392,
+ "name" : "HAL_DATASPACE_DCI_P3_LINEAR"
+ },
+ {
+ "enum_field_value" : 155844608,
+ "name" : "HAL_DATASPACE_DCI_P3"
+ },
+ {
+ "enum_field_value" : 139067392,
+ "name" : "HAL_DATASPACE_DISPLAY_P3_LINEAR"
+ },
+ {
+ "enum_field_value" : 143261696,
+ "name" : "HAL_DATASPACE_DISPLAY_P3"
+ },
+ {
+ "enum_field_value" : 151715840,
+ "name" : "HAL_DATASPACE_ADOBE_RGB"
+ },
+ {
+ "enum_field_value" : 138805248,
+ "name" : "HAL_DATASPACE_BT2020_LINEAR"
+ },
+ {
+ "enum_field_value" : 147193856,
+ "name" : "HAL_DATASPACE_BT2020"
+ },
+ {
+ "enum_field_value" : 163971072,
+ "name" : "HAL_DATASPACE_BT2020_PQ"
+ },
+ {
+ "enum_field_value" : 4096,
+ "name" : "HAL_DATASPACE_DEPTH"
+ },
+ {
+ "enum_field_value" : 4097,
+ "name" : "HAL_DATASPACE_SENSOR"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_dataspace_t",
+ "name" : "android_dataspace_t",
+ "referenced_type" : "_ZTI19android_dataspace_t",
+ "self_type" : "_ZTI19android_dataspace_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "FLEX_FORMAT_INVALID"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "FLEX_FORMAT_Y"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "FLEX_FORMAT_YCbCr"
+ },
+ {
+ "enum_field_value" : 1073741831,
+ "name" : "FLEX_FORMAT_YCbCrA"
+ },
+ {
+ "enum_field_value" : 7168,
+ "name" : "FLEX_FORMAT_RGB"
+ },
+ {
+ "enum_field_value" : 1073748992,
+ "name" : "FLEX_FORMAT_RGBA"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_flex_format",
+ "name" : "android_flex_format",
+ "referenced_type" : "_ZTI19android_flex_format",
+ "self_type" : "_ZTI19android_flex_format",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_TRANSFORM_FLIP_H"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_TRANSFORM_FLIP_V"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_TRANSFORM_ROT_90"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_TRANSFORM_ROT_180"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "HAL_TRANSFORM_ROT_270"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_transform_t",
+ "name" : "android_transform_t",
+ "referenced_type" : "_ZTI19android_transform_t",
+ "self_type" : "_ZTI19android_transform_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_COLOR_MODE_NATIVE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_625"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_525"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "HAL_COLOR_MODE_STANDARD_BT709"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "HAL_COLOR_MODE_DCI_P3"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "HAL_COLOR_MODE_SRGB"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "HAL_COLOR_MODE_ADOBE_RGB"
+ },
+ {
+ "enum_field_value" : 9,
+ "name" : "HAL_COLOR_MODE_DISPLAY_P3"
+ }
+ ],
+ "linker_set_key" : "_ZTI20android_color_mode_t",
+ "name" : "android_color_mode_t",
+ "referenced_type" : "_ZTI20android_color_mode_t",
+ "self_type" : "_ZTI20android_color_mode_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "SYSTEM_TIME_REALTIME"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "SYSTEM_TIME_MONOTONIC"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "SYSTEM_TIME_PROCESS"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "SYSTEM_TIME_THREAD"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "SYSTEM_TIME_BOOTTIME"
+ }
+ ],
+ "linker_set_key" : "_ZTI21$SYSTEM_TIME_BOOTTIME",
+ "name" : "(unnamed)",
+ "referenced_type" : "_ZTI21$SYSTEM_TIME_BOOTTIME",
+ "self_type" : "_ZTI21$SYSTEM_TIME_BOOTTIME",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Timers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "FLEX_COMPONENT_Y"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "FLEX_COMPONENT_Cb"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "FLEX_COMPONENT_Cr"
+ },
+ {
+ "enum_field_value" : 1024,
+ "name" : "FLEX_COMPONENT_R"
+ },
+ {
+ "enum_field_value" : 2048,
+ "name" : "FLEX_COMPONENT_G"
+ },
+ {
+ "enum_field_value" : 4096,
+ "name" : "FLEX_COMPONENT_B"
+ },
+ {
+ "enum_field_value" : 1073741824,
+ "name" : "FLEX_COMPONENT_A"
+ }
+ ],
+ "linker_set_key" : "_ZTI22android_flex_component",
+ "name" : "android_flex_component",
+ "referenced_type" : "_ZTI22android_flex_component",
+ "self_type" : "_ZTI22android_flex_component",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_PIXEL_FORMAT_RGBA_8888"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_PIXEL_FORMAT_RGBX_8888"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_PIXEL_FORMAT_RGB_888"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_PIXEL_FORMAT_RGB_565"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "HAL_PIXEL_FORMAT_BGRA_8888"
+ },
+ {
+ "enum_field_value" : 16,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_422_SP"
+ },
+ {
+ "enum_field_value" : 17,
+ "name" : "HAL_PIXEL_FORMAT_YCRCB_420_SP"
+ },
+ {
+ "enum_field_value" : 20,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_422_I"
+ },
+ {
+ "enum_field_value" : 22,
+ "name" : "HAL_PIXEL_FORMAT_RGBA_FP16"
+ },
+ {
+ "enum_field_value" : 32,
+ "name" : "HAL_PIXEL_FORMAT_RAW16"
+ },
+ {
+ "enum_field_value" : 33,
+ "name" : "HAL_PIXEL_FORMAT_BLOB"
+ },
+ {
+ "enum_field_value" : 34,
+ "name" : "HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED"
+ },
+ {
+ "enum_field_value" : 35,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_420_888"
+ },
+ {
+ "enum_field_value" : 36,
+ "name" : "HAL_PIXEL_FORMAT_RAW_OPAQUE"
+ },
+ {
+ "enum_field_value" : 37,
+ "name" : "HAL_PIXEL_FORMAT_RAW10"
+ },
+ {
+ "enum_field_value" : 38,
+ "name" : "HAL_PIXEL_FORMAT_RAW12"
+ },
+ {
+ "enum_field_value" : 43,
+ "name" : "HAL_PIXEL_FORMAT_RGBA_1010102"
+ },
+ {
+ "enum_field_value" : 538982489,
+ "name" : "HAL_PIXEL_FORMAT_Y8"
+ },
+ {
+ "enum_field_value" : 540422489,
+ "name" : "HAL_PIXEL_FORMAT_Y16"
+ },
+ {
+ "enum_field_value" : 842094169,
+ "name" : "HAL_PIXEL_FORMAT_YV12"
+ }
+ ],
+ "linker_set_key" : "_ZTI22android_pixel_format_t",
+ "name" : "android_pixel_format_t",
+ "referenced_type" : "_ZTI22android_pixel_format_t",
+ "self_type" : "_ZTI22android_pixel_format_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 19,
+ "name" : "ANDROID_PRIORITY_LOWEST"
+ },
+ {
+ "enum_field_value" : 10,
+ "name" : "ANDROID_PRIORITY_BACKGROUND"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "ANDROID_PRIORITY_NORMAL"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "ANDROID_PRIORITY_FOREGROUND"
+ },
+ {
+ "enum_field_value" : -4,
+ "name" : "ANDROID_PRIORITY_DISPLAY"
+ },
+ {
+ "enum_field_value" : -8,
+ "name" : "ANDROID_PRIORITY_URGENT_DISPLAY"
+ },
+ {
+ "enum_field_value" : -10,
+ "name" : "ANDROID_PRIORITY_VIDEO"
+ },
+ {
+ "enum_field_value" : -16,
+ "name" : "ANDROID_PRIORITY_AUDIO"
+ },
+ {
+ "enum_field_value" : -19,
+ "name" : "ANDROID_PRIORITY_URGENT_AUDIO"
+ },
+ {
+ "enum_field_value" : -20,
+ "name" : "ANDROID_PRIORITY_HIGHEST"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "ANDROID_PRIORITY_DEFAULT"
+ },
+ {
+ "enum_field_value" : -1,
+ "name" : "ANDROID_PRIORITY_MORE_FAVORABLE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "ANDROID_PRIORITY_LESS_FAVORABLE"
+ }
+ ],
+ "linker_set_key" : "_ZTI23$ANDROID_PRIORITY_AUDIO",
+ "name" : "(unnamed)",
+ "referenced_type" : "_ZTI23$ANDROID_PRIORITY_AUDIO",
+ "self_type" : "_ZTI23$ANDROID_PRIORITY_AUDIO",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/thread_defs.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 281411584,
+ "name" : "HAL_DATASPACE_BT2020_ITU"
+ },
+ {
+ "enum_field_value" : 298188800,
+ "name" : "HAL_DATASPACE_BT2020_ITU_PQ"
+ },
+ {
+ "enum_field_value" : 302383104,
+ "name" : "HAL_DATASPACE_BT2020_ITU_HLG"
+ },
+ {
+ "enum_field_value" : 168165376,
+ "name" : "HAL_DATASPACE_BT2020_HLG"
+ }
+ ],
+ "linker_set_key" : "_ZTI24android_dataspace_v1_1_t",
+ "name" : "android_dataspace_v1_1_t",
+ "referenced_type" : "_ZTI24android_dataspace_v1_1_t",
+ "self_type" : "_ZTI24android_dataspace_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 142999552,
+ "name" : "HAL_DATASPACE_DISPLAY_BT2020"
+ },
+ {
+ "enum_field_value" : 4098,
+ "name" : "HAL_DATASPACE_DYNAMIC_DEPTH"
+ },
+ {
+ "enum_field_value" : 4099,
+ "name" : "HAL_DATASPACE_JPEG_APP_SEGMENTS"
+ },
+ {
+ "enum_field_value" : 4100,
+ "name" : "HAL_DATASPACE_HEIF"
+ }
+ ],
+ "linker_set_key" : "_ZTI24android_dataspace_v1_2_t",
+ "name" : "android_dataspace_v1_2_t",
+ "referenced_type" : "_ZTI24android_dataspace_v1_2_t",
+ "self_type" : "_ZTI24android_dataspace_v1_2_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.2.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 10,
+ "name" : "HAL_COLOR_MODE_BT2020"
+ },
+ {
+ "enum_field_value" : 11,
+ "name" : "HAL_COLOR_MODE_BT2100_PQ"
+ },
+ {
+ "enum_field_value" : 12,
+ "name" : "HAL_COLOR_MODE_BT2100_HLG"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_color_mode_v1_1_t",
+ "name" : "android_color_mode_v1_1_t",
+ "referenced_type" : "_ZTI25android_color_mode_v1_1_t",
+ "self_type" : "_ZTI25android_color_mode_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_COLOR_TRANSFORM_IDENTITY"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_COLOR_TRANSFORM_VALUE_INVERSE"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_COLOR_TRANSFORM_GRAYSCALE"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_color_transform_t",
+ "name" : "android_color_transform_t",
+ "referenced_type" : "_ZTI25android_color_transform_t",
+ "self_type" : "_ZTI25android_color_transform_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.0.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 39,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_422_888"
+ },
+ {
+ "enum_field_value" : 40,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_444_888"
+ },
+ {
+ "enum_field_value" : 41,
+ "name" : "HAL_PIXEL_FORMAT_FLEX_RGB_888"
+ },
+ {
+ "enum_field_value" : 42,
+ "name" : "HAL_PIXEL_FORMAT_FLEX_RGBA_8888"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_pixel_format_sw_t",
+ "name" : "android_pixel_format_sw_t",
+ "referenced_type" : "_ZTI25android_pixel_format_sw_t",
+ "self_type" : "_ZTI25android_pixel_format_sw_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-sw.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 48,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_16"
+ },
+ {
+ "enum_field_value" : 49,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_24"
+ },
+ {
+ "enum_field_value" : 50,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8"
+ },
+ {
+ "enum_field_value" : 51,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_32F"
+ },
+ {
+ "enum_field_value" : 52,
+ "name" : "HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8"
+ },
+ {
+ "enum_field_value" : 53,
+ "name" : "HAL_PIXEL_FORMAT_STENCIL_8"
+ },
+ {
+ "enum_field_value" : 54,
+ "name" : "HAL_PIXEL_FORMAT_YCBCR_P010"
+ }
+ ],
+ "linker_set_key" : "_ZTI27android_pixel_format_v1_1_t",
+ "name" : "android_pixel_format_v1_1_t",
+ "referenced_type" : "_ZTI27android_pixel_format_v1_1_t",
+ "self_type" : "_ZTI27android_pixel_format_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 55,
+ "name" : "HAL_PIXEL_FORMAT_HSV_888"
+ }
+ ],
+ "linker_set_key" : "_ZTI27android_pixel_format_v1_2_t",
+ "name" : "android_pixel_format_v1_2_t",
+ "referenced_type" : "_ZTI27android_pixel_format_v1_2_t",
+ "self_type" : "_ZTI27android_pixel_format_v1_2_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.2.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "HAL_RENDER_INTENT_COLORIMETRIC"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "HAL_RENDER_INTENT_ENHANCE"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "HAL_RENDER_INTENT_TONE_MAP_COLORIMETRIC"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "HAL_RENDER_INTENT_TONE_MAP_ENHANCE"
+ }
+ ],
+ "linker_set_key" : "_ZTI28android_render_intent_v1_1_t",
+ "name" : "android_render_intent_v1_1_t",
+ "referenced_type" : "_ZTI28android_render_intent_v1_1_t",
+ "self_type" : "_ZTI28android_render_intent_v1_1_t",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics-base-v1.1.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "LOG_ID_MIN"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "LOG_ID_MAIN"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "LOG_ID_RADIO"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "LOG_ID_EVENTS"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "LOG_ID_SYSTEM"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "LOG_ID_CRASH"
+ },
+ {
+ "enum_field_value" : 5,
+ "name" : "LOG_ID_STATS"
+ },
+ {
+ "enum_field_value" : 6,
+ "name" : "LOG_ID_SECURITY"
+ },
+ {
+ "enum_field_value" : 7,
+ "name" : "LOG_ID_KERNEL"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "LOG_ID_MAX"
+ },
+ {
+ "enum_field_value" : 2147483647,
+ "name" : "LOG_ID_DEFAULT"
+ }
+ ],
+ "linker_set_key" : "_ZTI6log_id",
+ "name" : "log_id",
+ "referenced_type" : "_ZTI6log_id",
+ "self_type" : "_ZTI6log_id",
+ "size" : 4,
+ "source_file" : "system/logging/liblog/include_vndk/android/log.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::VectorImpl::HAS_TRIVIAL_CTOR"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "android::VectorImpl::HAS_TRIVIAL_DTOR"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "android::VectorImpl::HAS_TRIVIAL_COPY"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android10VectorImpl17$HAS_TRIVIAL_COPYE",
+ "name" : "android::VectorImpl::(unnamed)",
+ "referenced_type" : "_ZTIN7android10VectorImpl17$HAS_TRIVIAL_COPYE",
+ "self_type" : "_ZTIN7android10VectorImpl17$HAS_TRIVIAL_COPYE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_pointer<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_pointer<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_pointer<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_pointer<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_pointer<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_pointer<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::OK"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::NO_ERROR"
+ },
+ {
+ "enum_field_value" : -2147483648,
+ "name" : "android::UNKNOWN_ERROR"
+ },
+ {
+ "enum_field_value" : -12,
+ "name" : "android::NO_MEMORY"
+ },
+ {
+ "enum_field_value" : -38,
+ "name" : "android::INVALID_OPERATION"
+ },
+ {
+ "enum_field_value" : -22,
+ "name" : "android::BAD_VALUE"
+ },
+ {
+ "enum_field_value" : -2147483647,
+ "name" : "android::BAD_TYPE"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "android::NAME_NOT_FOUND"
+ },
+ {
+ "enum_field_value" : -1,
+ "name" : "android::PERMISSION_DENIED"
+ },
+ {
+ "enum_field_value" : -19,
+ "name" : "android::NO_INIT"
+ },
+ {
+ "enum_field_value" : -17,
+ "name" : "android::ALREADY_EXISTS"
+ },
+ {
+ "enum_field_value" : -32,
+ "name" : "android::DEAD_OBJECT"
+ },
+ {
+ "enum_field_value" : -2147483646,
+ "name" : "android::FAILED_TRANSACTION"
+ },
+ {
+ "enum_field_value" : -75,
+ "name" : "android::BAD_INDEX"
+ },
+ {
+ "enum_field_value" : -61,
+ "name" : "android::NOT_ENOUGH_DATA"
+ },
+ {
+ "enum_field_value" : -11,
+ "name" : "android::WOULD_BLOCK"
+ },
+ {
+ "enum_field_value" : -110,
+ "name" : "android::TIMED_OUT"
+ },
+ {
+ "enum_field_value" : -74,
+ "name" : "android::UNKNOWN_TRANSACTION"
+ },
+ {
+ "enum_field_value" : -2147483641,
+ "name" : "android::FDS_NOT_ALLOWED"
+ },
+ {
+ "enum_field_value" : -2147483640,
+ "name" : "android::UNEXPECTED_NULL"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android15$ALREADY_EXISTSE",
+ "name" : "android::(unnamed)",
+ "referenced_type" : "_ZTIN7android15$ALREADY_EXISTSE",
+ "self_type" : "_ZTIN7android15$ALREADY_EXISTSE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Errors.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 19,
+ "name" : "android::PRIORITY_LOWEST"
+ },
+ {
+ "enum_field_value" : 10,
+ "name" : "android::PRIORITY_BACKGROUND"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::PRIORITY_NORMAL"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "android::PRIORITY_FOREGROUND"
+ },
+ {
+ "enum_field_value" : -4,
+ "name" : "android::PRIORITY_DISPLAY"
+ },
+ {
+ "enum_field_value" : -8,
+ "name" : "android::PRIORITY_URGENT_DISPLAY"
+ },
+ {
+ "enum_field_value" : -16,
+ "name" : "android::PRIORITY_AUDIO"
+ },
+ {
+ "enum_field_value" : -19,
+ "name" : "android::PRIORITY_URGENT_AUDIO"
+ },
+ {
+ "enum_field_value" : -20,
+ "name" : "android::PRIORITY_HIGHEST"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::PRIORITY_DEFAULT"
+ },
+ {
+ "enum_field_value" : -1,
+ "name" : "android::PRIORITY_MORE_FAVORABLE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::PRIORITY_LESS_FAVORABLE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android15$PRIORITY_AUDIOE",
+ "name" : "android::(unnamed)",
+ "referenced_type" : "_ZTIN7android15$PRIORITY_AUDIOE",
+ "self_type" : "_ZTIN7android15$PRIORITY_AUDIOE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/ThreadDefs.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_copy<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_copy<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_copy<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_copy<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_copy<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_copy<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIbE6$valueE",
+ "name" : "android::trait_trivial_copy<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIcE6$valueE",
+ "name" : "android::trait_trivial_copy<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIdE6$valueE",
+ "name" : "android::trait_trivial_copy<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIfE6$valueE",
+ "name" : "android::trait_trivial_copy<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIhE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIiE6$valueE",
+ "name" : "android::trait_trivial_copy<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIjE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIlE6$valueE",
+ "name" : "android::trait_trivial_copy<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyImE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIsE6$valueE",
+ "name" : "android::trait_trivial_copy<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyItE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIvE6$valueE",
+ "name" : "android::trait_trivial_copy<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIxE6$valueE",
+ "name" : "android::trait_trivial_copy<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_copy<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIyE6$valueE",
+ "name" : "android::trait_trivial_copy<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_ctor<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_ctor<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_ctor<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_ctor<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_ctor<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_ctor<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIbE6$valueE",
+ "name" : "android::trait_trivial_ctor<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIcE6$valueE",
+ "name" : "android::trait_trivial_ctor<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIdE6$valueE",
+ "name" : "android::trait_trivial_ctor<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIfE6$valueE",
+ "name" : "android::trait_trivial_ctor<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIhE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIiE6$valueE",
+ "name" : "android::trait_trivial_ctor<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIjE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIlE6$valueE",
+ "name" : "android::trait_trivial_ctor<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorImE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIsE6$valueE",
+ "name" : "android::trait_trivial_ctor<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorItE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIvE6$valueE",
+ "name" : "android::trait_trivial_ctor<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIxE6$valueE",
+ "name" : "android::trait_trivial_ctor<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_ctor<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIyE6$valueE",
+ "name" : "android::trait_trivial_ctor<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_dtor<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_dtor<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_dtor<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_dtor<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_dtor<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_dtor<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIbE6$valueE",
+ "name" : "android::trait_trivial_dtor<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIcE6$valueE",
+ "name" : "android::trait_trivial_dtor<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIdE6$valueE",
+ "name" : "android::trait_trivial_dtor<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIfE6$valueE",
+ "name" : "android::trait_trivial_dtor<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIhE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIiE6$valueE",
+ "name" : "android::trait_trivial_dtor<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIjE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIlE6$valueE",
+ "name" : "android::trait_trivial_dtor<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorImE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIsE6$valueE",
+ "name" : "android::trait_trivial_dtor<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorItE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIvE6$valueE",
+ "name" : "android::trait_trivial_dtor<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIxE6$valueE",
+ "name" : "android::trait_trivial_dtor<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_dtor<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIyE6$valueE",
+ "name" : "android::trait_trivial_dtor<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_move<android::sysprop_change_callback_info>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEE6$valueE",
+ "name" : "android::trait_trivial_move<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_move<android::Looper::MessageEnvelope>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEE6$valueE",
+ "name" : "android::trait_trivial_move<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::trait_trivial_move<android::Looper::Response>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEE6$valueE",
+ "name" : "android::trait_trivial_move<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<android::String8>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_7String8EE6$valueE",
+ "name" : "android::trait_trivial_move<android::String8>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<android::String16>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_8String16EE6$valueE",
+ "name" : "android::trait_trivial_move<android::String16>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<bool>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIbE6$valueE",
+ "name" : "android::trait_trivial_move<bool>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIbE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIbE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIcE6$valueE",
+ "name" : "android::trait_trivial_move<char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIcE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIcE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<double>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIdE6$valueE",
+ "name" : "android::trait_trivial_move<double>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIdE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIdE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<float>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIfE6$valueE",
+ "name" : "android::trait_trivial_move<float>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIfE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIfE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned char>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIhE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned char>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIhE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIhE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIiE6$valueE",
+ "name" : "android::trait_trivial_move<int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIiE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIiE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned int>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIjE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned int>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIjE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIjE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIlE6$valueE",
+ "name" : "android::trait_trivial_move<long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIlE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIlE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveImE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveImE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveImE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIsE6$valueE",
+ "name" : "android::trait_trivial_move<short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIsE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIsE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned short>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveItE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned short>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveItE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveItE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<void>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIvE6$valueE",
+ "name" : "android::trait_trivial_move<void>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIvE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIvE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIxE6$valueE",
+ "name" : "android::trait_trivial_move<long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIxE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIxE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::trait_trivial_move<unsigned long long>::value"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIyE6$valueE",
+ "name" : "android::trait_trivial_move<unsigned long long>::(unnamed)",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIyE6$valueE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIyE6$valueE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::Mutex::PRIVATE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Mutex::SHARED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android5Mutex8$PRIVATEE",
+ "name" : "android::Mutex::(unnamed)",
+ "referenced_type" : "_ZTIN7android5Mutex8$PRIVATEE",
+ "self_type" : "_ZTIN7android5Mutex8$PRIVATEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Looper::EVENT_INPUT"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "android::Looper::EVENT_OUTPUT"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "android::Looper::EVENT_ERROR"
+ },
+ {
+ "enum_field_value" : 8,
+ "name" : "android::Looper::EVENT_HANGUP"
+ },
+ {
+ "enum_field_value" : 16,
+ "name" : "android::Looper::EVENT_INVALID"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper12$EVENT_ERRORE",
+ "name" : "android::Looper::(unnamed)",
+ "referenced_type" : "_ZTIN7android6Looper12$EVENT_ERRORE",
+ "self_type" : "_ZTIN7android6Looper12$EVENT_ERRORE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : -1,
+ "name" : "android::Looper::POLL_WAKE"
+ },
+ {
+ "enum_field_value" : -2,
+ "name" : "android::Looper::POLL_CALLBACK"
+ },
+ {
+ "enum_field_value" : -3,
+ "name" : "android::Looper::POLL_TIMEOUT"
+ },
+ {
+ "enum_field_value" : -4,
+ "name" : "android::Looper::POLL_ERROR"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper14$POLL_CALLBACKE",
+ "name" : "android::Looper::(unnamed)",
+ "referenced_type" : "_ZTIN7android6Looper14$POLL_CALLBACKE",
+ "self_type" : "_ZTIN7android6Looper14$POLL_CALLBACKE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "underlying_type" : "_ZTIi"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Looper::PREPARE_ALLOW_NON_CALLBACKS"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper28$PREPARE_ALLOW_NON_CALLBACKSE",
+ "name" : "android::Looper::(unnamed)",
+ "referenced_type" : "_ZTIN7android6Looper28$PREPARE_ALLOW_NON_CALLBACKSE",
+ "self_type" : "_ZTIN7android6Looper28$PREPARE_ALLOW_NON_CALLBACKSE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::RWLock::PRIVATE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RWLock::SHARED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLock8$PRIVATEE",
+ "name" : "android::RWLock::(unnamed)",
+ "referenced_type" : "_ZTIN7android6RWLock8$PRIVATEE",
+ "self_type" : "_ZTIN7android6RWLock8$PRIVATEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::is_pointer"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_ctor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_dtor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_copy"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::sysprop_change_callback_info>::has_trivial_move"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEE17$has_trivial_copyE",
+ "name" : "android::traits<android::sysprop_change_callback_info>::(unnamed)",
+ "referenced_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEE17$has_trivial_copyE",
+ "self_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEE17$has_trivial_copyE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::is_pointer"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_ctor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_dtor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_copy"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::MessageEnvelope>::has_trivial_move"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEE17$has_trivial_copyE",
+ "name" : "android::traits<android::Looper::MessageEnvelope>::(unnamed)",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEE17$has_trivial_copyE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEE17$has_trivial_copyE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::is_pointer"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_ctor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_dtor"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_copy"
+ },
+ {
+ "enum_field_value" : 0,
+ "name" : "android::traits<android::Looper::Response>::has_trivial_move"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper8ResponseEE17$has_trivial_copyE",
+ "name" : "android::traits<android::Looper::Response>::(unnamed)",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEE17$has_trivial_copyE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEE17$has_trivial_copyE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::FileMap::NORMAL"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::FileMap::RANDOM"
+ },
+ {
+ "enum_field_value" : 2,
+ "name" : "android::FileMap::SEQUENTIAL"
+ },
+ {
+ "enum_field_value" : 3,
+ "name" : "android::FileMap::WILLNEED"
+ },
+ {
+ "enum_field_value" : 4,
+ "name" : "android::FileMap::DONTNEED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7FileMap9MapAdviceE",
+ "name" : "android::FileMap::MapAdvice",
+ "referenced_type" : "_ZTIN7android7FileMap9MapAdviceE",
+ "self_type" : "_ZTIN7android7FileMap9MapAdviceE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "access" : "protected",
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RefBase::FIRST_INC_STRONG"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7RefBase17$FIRST_INC_STRONGE",
+ "name" : "android::RefBase::(unnamed)",
+ "referenced_type" : "_ZTIN7android7RefBase17$FIRST_INC_STRONGE",
+ "self_type" : "_ZTIN7android7RefBase17$FIRST_INC_STRONGE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "access" : "protected",
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::RefBase::OBJECT_LIFETIME_STRONG"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RefBase::OBJECT_LIFETIME_WEAK"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::RefBase::OBJECT_LIFETIME_MASK"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7RefBase21$OBJECT_LIFETIME_MASKE",
+ "name" : "android::RefBase::(unnamed)",
+ "referenced_type" : "_ZTIN7android7RefBase21$OBJECT_LIFETIME_MASKE",
+ "self_type" : "_ZTIN7android7RefBase21$OBJECT_LIFETIME_MASKE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::Condition::WAKE_UP_ONE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Condition::WAKE_UP_ALL"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9Condition10WakeUpTypeE",
+ "name" : "android::Condition::WakeUpType",
+ "referenced_type" : "_ZTIN7android9Condition10WakeUpTypeE",
+ "self_type" : "_ZTIN7android9Condition10WakeUpTypeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Condition.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 0,
+ "name" : "android::Condition::PRIVATE"
+ },
+ {
+ "enum_field_value" : 1,
+ "name" : "android::Condition::SHARED"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9Condition8$PRIVATEE",
+ "name" : "android::Condition::(unnamed)",
+ "referenced_type" : "_ZTIN7android9Condition8$PRIVATEE",
+ "self_type" : "_ZTIN7android9Condition8$PRIVATEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Condition.h",
+ "underlying_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "alignment" : 4,
+ "enum_fields" :
+ [
+ {
+ "enum_field_value" : 20,
+ "name" : "android::FdPrinter::MAX_FORMAT_STRING"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9FdPrinter18$MAX_FORMAT_STRINGE",
+ "name" : "android::FdPrinter::(unnamed)",
+ "referenced_type" : "_ZTIN7android9FdPrinter18$MAX_FORMAT_STRINGE",
+ "self_type" : "_ZTIN7android9FdPrinter18$MAX_FORMAT_STRINGE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "underlying_type" : "_ZTIj"
+ }
+ ],
+ "function_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPFiPvES_PKcijPS_E",
+ "name" : "int (int (*)(void *), void *, const char *, int, unsigned int, void **)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPFiPvES_PKcijPS_E",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPFiPvES_PKcijPS_E",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPKvS0_E",
+ "name" : "int (const void *, const void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPKvS0_E",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPKvS0_E",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiPKvS0_PvE",
+ "name" : "int (const void *, const void *, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiPKvS0_PvE",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiPKvS0_PvE",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.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/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFiiiPvE",
+ "name" : "int (int, int, void *)",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "referenced_type" : "_ZTIFiiiPvE",
+ "return_type" : "_ZTIi",
+ "self_type" : "_ZTIFiiiPvE",
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIFvvE",
+ "name" : "void ()",
+ "referenced_type" : "_ZTIFvvE",
+ "return_type" : "_ZTIv",
+ "self_type" : "_ZTIFvvE",
+ "source_file" : "system/core/libutils/include/utils/misc.h"
+ }
+ ],
+ "functions" :
+ [
+ {
+ "access" : "private",
+ "function_name" : "android::LogPrinter::printRaw",
+ "linker_set_key" : "_ZN7android10LogPrinter8printRawEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::LogPrinter::printLine",
+ "linker_set_key" : "_ZN7android10LogPrinter9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::LogPrinter::LogPrinter",
+ "linker_set_key" : "_ZN7android10LogPrinterC1EPKc19android_LogPriorityS2_b",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTI19android_LogPriority"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::LogPrinter::LogPrinter",
+ "linker_set_key" : "_ZN7android10LogPrinterC2EPKc19android_LogPriorityS2_b",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10LogPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTI19android_LogPriority"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::appendArray",
+ "linker_set_key" : "_ZN7android10VectorImpl11appendArrayEPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::setCapacity",
+ "linker_set_key" : "_ZN7android10VectorImpl11setCapacityEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::appendVector",
+ "linker_set_key" : "_ZN7android10VectorImpl12appendVectorERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::editArrayImpl",
+ "linker_set_key" : "_ZN7android10VectorImpl13editArrayImplEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::finish_vector",
+ "linker_set_key" : "_ZN7android10VectorImpl13finish_vectorEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertArrayAt",
+ "linker_set_key" : "_ZN7android10VectorImpl13insertArrayAtEPKvjj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::removeItemsAt",
+ "linker_set_key" : "_ZN7android10VectorImpl13removeItemsAtEjj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertVectorAt",
+ "linker_set_key" : "_ZN7android10VectorImpl14insertVectorAtERKS0_j",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::VectorImpl::release_storage",
+ "linker_set_key" : "_ZN7android10VectorImpl15release_storageEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::editItemLocation",
+ "linker_set_key" : "_ZN7android10VectorImpl16editItemLocationEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::add",
+ "linker_set_key" : "_ZN7android10VectorImpl3addEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::add",
+ "linker_set_key" : "_ZN7android10VectorImpl3addEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::pop",
+ "linker_set_key" : "_ZN7android10VectorImpl3popEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::push",
+ "linker_set_key" : "_ZN7android10VectorImpl4pushEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::push",
+ "linker_set_key" : "_ZN7android10VectorImpl4pushEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::sort",
+ "linker_set_key" : "_ZN7android10VectorImpl4sortEPFiPKvS2_E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiPKvS0_E"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::sort",
+ "linker_set_key" : "_ZN7android10VectorImpl4sortEPFiPKvS2_PvES3_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiPKvS0_PvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::VectorImpl::_grow",
+ "linker_set_key" : "_ZN7android10VectorImpl5_growEjj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::clear",
+ "linker_set_key" : "_ZN7android10VectorImpl5clearEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::resize",
+ "linker_set_key" : "_ZN7android10VectorImpl6resizeEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::VectorImpl::_shrink",
+ "linker_set_key" : "_ZN7android10VectorImpl7_shrinkEjj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertAt",
+ "linker_set_key" : "_ZN7android10VectorImpl8insertAtEPKvjj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::insertAt",
+ "linker_set_key" : "_ZN7android10VectorImpl8insertAtEjj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::replaceAt",
+ "linker_set_key" : "_ZN7android10VectorImpl9replaceAtEPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::replaceAt",
+ "linker_set_key" : "_ZN7android10VectorImpl9replaceAtEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplC2ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplC2Ejj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::~VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::~VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::~VectorImpl",
+ "linker_set_key" : "_ZN7android10VectorImplD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::operator=",
+ "linker_set_key" : "_ZN7android10VectorImplaSERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIRN7android10VectorImplE",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::uptimeNanos",
+ "linker_set_key" : "_ZN7android11uptimeNanosEv",
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::NativeHandle::create",
+ "linker_set_key" : "_ZN7android12NativeHandle6createEP13native_handleb",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleC1EP13native_handleb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ },
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleC2EP13native_handleb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ },
+ {
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::~NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::NativeHandle::~NativeHandle",
+ "linker_set_key" : "_ZN7android12NativeHandleD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "function_name" : "android::uptimeMillis",
+ "linker_set_key" : "_ZN7android12uptimeMillisEv",
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::PrefixPrinter::printLine",
+ "linker_set_key" : "_ZN7android13PrefixPrinter9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android13PrefixPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::PrefixPrinter::PrefixPrinter",
+ "linker_set_key" : "_ZN7android13PrefixPrinterC1ERNS_7PrinterEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android13PrefixPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIRN7android7PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::PrefixPrinter::PrefixPrinter",
+ "linker_set_key" : "_ZN7android13PrefixPrinterC2ERNS_7PrinterEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android13PrefixPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIRN7android7PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::LooperCallback::~LooperCallback",
+ "linker_set_key" : "_ZN7android14LooperCallbackD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::LooperCallback::~LooperCallback",
+ "linker_set_key" : "_ZN7android14LooperCallbackD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::LooperCallback::~LooperCallback",
+ "linker_set_key" : "_ZN7android14LooperCallbackD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::MessageHandler::~MessageHandler",
+ "linker_set_key" : "_ZN7android14MessageHandlerD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::MessageHandler::~MessageHandler",
+ "linker_set_key" : "_ZN7android14MessageHandlerD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::MessageHandler::~MessageHandler",
+ "linker_set_key" : "_ZN7android14MessageHandlerD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::String8Printer::printLine",
+ "linker_set_key" : "_ZN7android14String8Printer9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14String8PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::String8Printer::String8Printer",
+ "linker_set_key" : "_ZN7android14String8PrinterC1EPNS_7String8EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14String8PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::String8Printer::String8Printer",
+ "linker_set_key" : "_ZN7android14String8PrinterC2EPNS_7String8EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android14String8PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::statusToString",
+ "linker_set_key" : "_ZN7android14statusToStringEi",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTINSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE",
+ "source_file" : "system/core/libutils/include/utils/Errors.h"
+ },
+ {
+ "function_name" : "android::elapsedRealtime",
+ "linker_set_key" : "_ZN7android15elapsedRealtimeEv",
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::add",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl3addEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::merge",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl5mergeERKNS_10VectorImplE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::merge",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl5mergeERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::remove",
+ "linker_set_key" : "_ZN7android16SortedVectorImpl6removeEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplC2ERKNS_10VectorImplE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplC2Ejj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::~SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::~SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::~SortedVectorImpl",
+ "linker_set_key" : "_ZN7android16SortedVectorImplD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::operator=",
+ "linker_set_key" : "_ZN7android16SortedVectorImplaSERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android16SortedVectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIRN7android16SortedVectorImplE",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::JenkinsHashWhiten",
+ "linker_set_key" : "_ZN7android17JenkinsHashWhitenEj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "function_name" : "android::WeakMessageHandler::handleMessage",
+ "linker_set_key" : "_ZN7android18WeakMessageHandler13handleMessageERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::WeakMessageHandler::WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerC1ERKNS_2wpINS_14MessageHandlerEEE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::WeakMessageHandler::WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerC2ERKNS_2wpINS_14MessageHandlerEEE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::WeakMessageHandler::~WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::WeakMessageHandler::~WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::WeakMessageHandler::~WeakMessageHandler",
+ "linker_set_key" : "_ZN7android18WeakMessageHandlerD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android18WeakMessageHandlerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::JenkinsHashMixBytes",
+ "linker_set_key" : "_ZN7android19JenkinsHashMixBytesEjPKhj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "function_name" : "android::elapsedRealtimeNano",
+ "linker_set_key" : "_ZN7android19elapsedRealtimeNanoEv",
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libutils/include/utils/SystemClock.h"
+ },
+ {
+ "function_name" : "android::JenkinsHashMixShorts",
+ "linker_set_key" : "_ZN7android20JenkinsHashMixShortsEjPKtj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKt"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "function_name" : "android::SimpleLooperCallback::handleEvent",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallback11handleEventEiiPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::SimpleLooperCallback::SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackC1EPFiiiPvE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiiiPvE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::SimpleLooperCallback::SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackC2EPFiiiPvE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ },
+ {
+ "referenced_type" : "_ZTIPFiiiPvE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::SimpleLooperCallback::~SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::SimpleLooperCallback::~SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::SimpleLooperCallback::~SimpleLooperCallback",
+ "linker_set_key" : "_ZN7android20SimpleLooperCallbackD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::report_sysprop_change",
+ "linker_set_key" : "_ZN7android21report_sysprop_changeEv",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/misc.h"
+ },
+ {
+ "function_name" : "android::add_sysprop_change_callback",
+ "linker_set_key" : "_ZN7android27add_sysprop_change_callbackEPFvvEi",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFvvE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/misc.h"
+ },
+ {
+ "function_name" : "android::LightRefBase_reportIncStrongRequireStrongFailed",
+ "linker_set_key" : "_ZN7android47LightRefBase_reportIncStrongRequireStrongFailedEPKv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::initTLSKey",
+ "linker_set_key" : "_ZN7android6Looper10initTLSKeyEv",
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::sendMessage",
+ "linker_set_key" : "_ZN7android6Looper11sendMessageERKNS_2spINS_14MessageHandlerEEERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::getForThread",
+ "linker_set_key" : "_ZN7android6Looper12getForThreadEv",
+ "return_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::setForThread",
+ "linker_set_key" : "_ZN7android6Looper12setForThreadERKNS_2spIS0_EE",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_6LooperEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::removeMessages",
+ "linker_set_key" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::removeMessages",
+ "linker_set_key" : "_ZN7android6Looper14removeMessagesERKNS_2spINS_14MessageHandlerEEEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::threadDestructor",
+ "linker_set_key" : "_ZN7android6Looper16threadDestructorEPv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::sendMessageAtTime",
+ "linker_set_key" : "_ZN7android6Looper17sendMessageAtTimeExRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIx"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::rebuildEpollLocked",
+ "linker_set_key" : "_ZN7android6Looper18rebuildEpollLockedEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::sendMessageDelayed",
+ "linker_set_key" : "_ZN7android6Looper18sendMessageDelayedExRKNS_2spINS_14MessageHandlerEEERKNS_7MessageE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIx"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7MessageE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::removeSequenceNumberLocked",
+ "linker_set_key" : "_ZN7android6Looper26removeSequenceNumberLockedEy",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIy"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::scheduleEpollRebuildLocked",
+ "linker_set_key" : "_ZN7android6Looper26scheduleEpollRebuildLockedEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::wake",
+ "linker_set_key" : "_ZN7android6Looper4wakeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::addFd",
+ "linker_set_key" : "_ZN7android6Looper5addFdEiiiPFiiiPvES1_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPFiiiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::addFd",
+ "linker_set_key" : "_ZN7android6Looper5addFdEiiiRKNS_2spINS_14LooperCallbackEEEPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android2spINS_14LooperCallbackEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::awoken",
+ "linker_set_key" : "_ZN7android6Looper6awokenEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::pollAll",
+ "linker_set_key" : "_ZN7android6Looper7pollAllEiPiS1_PPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::prepare",
+ "linker_set_key" : "_ZN7android6Looper7prepareEi",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::pollOnce",
+ "linker_set_key" : "_ZN7android6Looper8pollOnceEiPiS1_PPv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPi"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::removeFd",
+ "linker_set_key" : "_ZN7android6Looper8removeFdEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Looper::pollInner",
+ "linker_set_key" : "_ZN7android6Looper9pollInnerEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::Looper",
+ "linker_set_key" : "_ZN7android6LooperC1Eb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::Looper",
+ "linker_set_key" : "_ZN7android6LooperC2Eb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Looper::~Looper",
+ "linker_set_key" : "_ZN7android6LooperD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Looper::~Looper",
+ "linker_set_key" : "_ZN7android6LooperD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Looper::~Looper",
+ "linker_set_key" : "_ZN7android6LooperD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Thread::readyToRun",
+ "linker_set_key" : "_ZN7android6Thread10readyToRunEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Thread::_threadLoop",
+ "linker_set_key" : "_ZN7android6Thread11_threadLoopEPv",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::requestExit",
+ "linker_set_key" : "_ZN7android6Thread11requestExitEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::requestExitAndWait",
+ "linker_set_key" : "_ZN7android6Thread18requestExitAndWaitEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::run",
+ "linker_set_key" : "_ZN7android6Thread3runEPKcij",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::join",
+ "linker_set_key" : "_ZN7android6Thread4joinEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::Thread",
+ "linker_set_key" : "_ZN7android6ThreadC2Eb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::~Thread",
+ "linker_set_key" : "_ZN7android6ThreadD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::~Thread",
+ "linker_set_key" : "_ZN7android6ThreadD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::~Thread",
+ "linker_set_key" : "_ZN7android6ThreadD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::FileMap::advise",
+ "linker_set_key" : "_ZN7android7FileMap6adviseENS0_9MapAdviceE",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIN7android7FileMap9MapAdviceE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::create",
+ "linker_set_key" : "_ZN7android7FileMap6createEPKcixjb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIx"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC1EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTION7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC2EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTION7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::FileMap",
+ "linker_set_key" : "_ZN7android7FileMapC2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::~FileMap",
+ "linker_set_key" : "_ZN7android7FileMapD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::~FileMap",
+ "linker_set_key" : "_ZN7android7FileMapD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::FileMap::operator=",
+ "linker_set_key" : "_ZN7android7FileMapaSEOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTION7android7FileMapE"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7FileMapE",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "function_name" : "android::Printer::printFormatLine",
+ "linker_set_key" : "_ZN7android7Printer15printFormatLineEPKcz",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::Printer",
+ "linker_set_key" : "_ZN7android7PrinterC2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::~Printer",
+ "linker_set_key" : "_ZN7android7PrinterD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::~Printer",
+ "linker_set_key" : "_ZN7android7PrinterD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Printer::~Printer",
+ "linker_set_key" : "_ZN7android7PrinterD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7PrinterE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onFirstRef",
+ "linker_set_key" : "_ZN7android7RefBase10onFirstRefEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::RefBase::renameRefs",
+ "linker_set_key" : "_ZN7android7RefBase10renameRefsEjRKNS_16ReferenceRenamerE",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android16ReferenceRenamerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::RefBase::renameRefId",
+ "linker_set_key" : "_ZN7android7RefBase11renameRefIdEPNS0_12weakref_typeEPKvS4_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::RefBase::renameRefId",
+ "linker_set_key" : "_ZN7android7RefBase11renameRefIdEPS0_PKvS3_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::attemptIncWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type14attemptIncWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::attemptIncStrong",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type16attemptIncStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::incWeakRequireWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type18incWeakRequireWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::decWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type7decWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::incWeak",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type7incWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::trackMe",
+ "linker_set_key" : "_ZN7android7RefBase12weakref_type7trackMeEbb",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onLastWeakRef",
+ "linker_set_key" : "_ZN7android7RefBase13onLastWeakRefEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onLastStrongRef",
+ "linker_set_key" : "_ZN7android7RefBase15onLastStrongRefEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::extendObjectLifetime",
+ "linker_set_key" : "_ZN7android7RefBase20extendObjectLifetimeEi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::onIncStrongAttempted",
+ "linker_set_key" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseC1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseC2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::~RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseD0Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::~RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::RefBase::~RefBase",
+ "linker_set_key" : "_ZN7android7RefBaseD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::String8::appendPath",
+ "linker_set_key" : "_ZN7android7String810appendPathEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::lockBuffer",
+ "linker_set_key" : "_ZN7android7String810lockBufferEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String8::real_append",
+ "linker_set_key" : "_ZN7android7String811real_appendEPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::appendFormat",
+ "linker_set_key" : "_ZN7android7String812appendFormatEPKcz",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::unlockBuffer",
+ "linker_set_key" : "_ZN7android7String812unlockBufferEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::unlockBuffer",
+ "linker_set_key" : "_ZN7android7String812unlockBufferEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::appendFormatV",
+ "linker_set_key" : "_ZN7android7String813appendFormatVEPKcSt9__va_list",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTISt9__va_list"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::convertToResPath",
+ "linker_set_key" : "_ZN7android7String816convertToResPathEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::clear",
+ "linker_set_key" : "_ZN7android7String85clearEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKDij",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToEPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::setTo",
+ "linker_set_key" : "_ZN7android7String85setToERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::append",
+ "linker_set_key" : "_ZN7android7String86appendEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::append",
+ "linker_set_key" : "_ZN7android7String86appendEPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::append",
+ "linker_set_key" : "_ZN7android7String86appendERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::format",
+ "linker_set_key" : "_ZN7android7String86formatEPKcz",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::formatV",
+ "linker_set_key" : "_ZN7android7String87formatVEPKcSt9__va_list",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTISt9__va_list"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::toLower",
+ "linker_set_key" : "_ZN7android7String87toLowerEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::removeAll",
+ "linker_set_key" : "_ZN7android7String89removeAllEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDij",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1EPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1ERKNS_8String16E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDi",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDij",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2EPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2ERKNS_8String16E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::String8",
+ "linker_set_key" : "_ZN7android7String8C2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::~String8",
+ "linker_set_key" : "_ZN7android7String8D1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::~String8",
+ "linker_set_key" : "_ZN7android7String8D2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::editResize",
+ "linker_set_key" : "_ZN7android8String1610editResizeEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::replaceAll",
+ "linker_set_key" : "_ZN7android8String1610replaceAllEDsDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::allocFromUTF8",
+ "linker_set_key" : "_ZN7android8String1613allocFromUTF8EPKcj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::allocFromUTF16",
+ "linker_set_key" : "_ZN7android8String1614allocFromUTF16EPKDsj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::edit",
+ "linker_set_key" : "_ZN7android8String164editEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::alloc",
+ "linker_set_key" : "_ZN7android8String165allocEj",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToEPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToEPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::setTo",
+ "linker_set_key" : "_ZN7android8String165setToERKS0_jj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::append",
+ "linker_set_key" : "_ZN7android8String166appendEPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::append",
+ "linker_set_key" : "_ZN7android8String166appendERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::insert",
+ "linker_set_key" : "_ZN7android8String166insertEjPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::insert",
+ "linker_set_key" : "_ZN7android8String166insertEjPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::acquire",
+ "linker_set_key" : "_ZN7android8String167acquireEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::release",
+ "linker_set_key" : "_ZN7android8String167releaseEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTION7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1EPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1ERKNS_7String8E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1ERKS0_jj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTION7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKDsj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2EPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2ERKNS_7String8E",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2ERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2ERKS0_jj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::String16",
+ "linker_set_key" : "_ZN7android8String16C2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::~String16",
+ "linker_set_key" : "_ZN7android8String16D1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::~String16",
+ "linker_set_key" : "_ZN7android8String16D2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::operator=",
+ "linker_set_key" : "_ZN7android8String16aSEOS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTION7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIRN7android8String16E",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::FdPrinter::printLine",
+ "linker_set_key" : "_ZN7android9FdPrinter9printLineEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9FdPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::FdPrinter::FdPrinter",
+ "linker_set_key" : "_ZN7android9FdPrinterC1EijPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9FdPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::FdPrinter::FdPrinter",
+ "linker_set_key" : "_ZN7android9FdPrinterC2EijPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9FdPrinterE"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "function_name" : "android::StopWatch::reset",
+ "linker_set_key" : "_ZN7android9StopWatch5resetEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchC1EPKci",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchC2EPKci",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::~StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::~StopWatch",
+ "linker_set_key" : "_ZN7android9StopWatchD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::fromContents",
+ "linker_set_key" : "_ZN7android9Tokenizer12fromContentsERKNS_7String8EPKcPPS0_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIPPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::skipDelimiters",
+ "linker_set_key" : "_ZN7android9Tokenizer14skipDelimitersEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::open",
+ "linker_set_key" : "_ZN7android9Tokenizer4openERKNS_7String8EPPS0_",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::nextLine",
+ "linker_set_key" : "_ZN7android9Tokenizer8nextLineEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::nextToken",
+ "linker_set_key" : "_ZN7android9Tokenizer9nextTokenEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Tokenizer::Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerC1ERKNS_7String8EPNS_7FileMapEPcbj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::Tokenizer::Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerC2ERKNS_7String8EPNS_7FileMapEPcbj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::~Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerD1Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::~Tokenizer",
+ "linker_set_key" : "_ZN7android9TokenizerD2Ev",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::itemLocation",
+ "linker_set_key" : "_ZNK7android10VectorImpl12itemLocationEj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android10VectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPKv",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::VectorImpl::capacity",
+ "linker_set_key" : "_ZNK7android10VectorImpl8capacityEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::VectorImpl::itemSize",
+ "linker_set_key" : "_ZNK7android10VectorImpl8itemSizeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android10VectorImplE"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::SortedVectorImpl::_indexOrderOf",
+ "linker_set_key" : "_ZNK7android16SortedVectorImpl13_indexOrderOfEPKvPj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::indexOf",
+ "linker_set_key" : "_ZNK7android16SortedVectorImpl7indexOfEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::SortedVectorImpl::orderOf",
+ "linker_set_key" : "_ZNK7android16SortedVectorImpl7orderOfEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android16SortedVectorImplE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "function_name" : "android::Looper::getAllowNonCallbacks",
+ "linker_set_key" : "_ZNK7android6Looper20getAllowNonCallbacksEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::Request::getEpollEvents",
+ "linker_set_key" : "_ZNK7android6Looper7Request14getEpollEventsEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6Looper7RequestE"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "function_name" : "android::Looper::isPolling",
+ "linker_set_key" : "_ZNK7android6Looper9isPollingEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6LooperE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Thread::exitPending",
+ "linker_set_key" : "_ZNK7android6Thread11exitPendingEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::getTid",
+ "linker_set_key" : "_ZNK7android6Thread6getTidEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "function_name" : "android::Thread::isRunning",
+ "linker_set_key" : "_ZNK7android6Thread9isRunningEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6ThreadE"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_destroy",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE10do_destroyEPvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_construct",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE12do_constructEPvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_move_forward",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE15do_move_forwardEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_move_backward",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE16do_move_backwardEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_copy",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE7do_copyEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::sysprop_change_callback_info>::do_splat",
+ "linker_set_key" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE8do_splatEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_destroy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE10do_destroyEPvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_construct",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE12do_constructEPvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_move_forward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE15do_move_forwardEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_move_backward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE16do_move_backwardEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_copy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE7do_copyEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::MessageEnvelope>::do_splat",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE8do_splatEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_destroy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE10do_destroyEPvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_construct",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE12do_constructEPvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_move_forward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE15do_move_forwardEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_move_backward",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE16do_move_backwardEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_copy",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE7do_copyEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "access" : "protected",
+ "function_name" : "android::Vector<android::Looper::Response>::do_splat",
+ "linker_set_key" : "_ZNK7android6VectorINS_6Looper8ResponseEE8do_splatEPvPKvj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "function_name" : "android::RefBase::createWeak",
+ "linker_set_key" : "_ZNK7android7RefBase10createWeakEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::getWeakRefs",
+ "linker_set_key" : "_ZNK7android7RefBase11getWeakRefsEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::getWeakCount",
+ "linker_set_key" : "_ZNK7android7RefBase12weakref_type12getWeakCountEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::refBase",
+ "linker_set_key" : "_ZNK7android7RefBase12weakref_type7refBaseEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "return_type" : "_ZTIPN7android7RefBaseE",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::weakref_type::printRefs",
+ "linker_set_key" : "_ZNK7android7RefBase12weakref_type9printRefsEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::forceIncStrong",
+ "linker_set_key" : "_ZNK7android7RefBase14forceIncStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::getStrongCount",
+ "linker_set_key" : "_ZNK7android7RefBase14getStrongCountEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::incStrongRequireStrong",
+ "linker_set_key" : "_ZNK7android7RefBase22incStrongRequireStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::decStrong",
+ "linker_set_key" : "_ZNK7android7RefBase9decStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::RefBase::incStrong",
+ "linker_set_key" : "_ZNK7android7RefBase9incStrongEPKv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7RefBaseE"
+ },
+ {
+ "referenced_type" : "_ZTIPKv"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "function_name" : "android::String8::getPathDir",
+ "linker_set_key" : "_ZNK7android7String810getPathDirEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getBasePath",
+ "linker_set_key" : "_ZNK7android7String811getBasePathEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathLeaf",
+ "linker_set_key" : "_ZNK7android7String811getPathLeafEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String8::find_extension",
+ "linker_set_key" : "_ZNK7android7String814find_extensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathExtension",
+ "linker_set_key" : "_ZNK7android7String816getPathExtensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::find",
+ "linker_set_key" : "_ZNK7android7String84findEPKcj",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::length",
+ "linker_set_key" : "_ZNK7android7String86lengthEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::walkPath",
+ "linker_set_key" : "_ZNK7android7String88walkPathEPS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String16::startsWith",
+ "linker_set_key" : "_ZNK7android8String1610startsWithEPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::startsWith",
+ "linker_set_key" : "_ZNK7android8String1610startsWithERKS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIRKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::isStaticString",
+ "linker_set_key" : "_ZNK7android8String1614isStaticStringEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String16::staticStringSize",
+ "linker_set_key" : "_ZNK7android8String1616staticStringSizeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::size",
+ "linker_set_key" : "_ZNK7android8String164sizeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::contains",
+ "linker_set_key" : "_ZNK7android8String168containsEPKDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIb",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::findLast",
+ "linker_set_key" : "_ZNK7android8String168findLastEDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::String16::findFirst",
+ "linker_set_key" : "_ZNK7android8String169findFirstEDs",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android8String16E"
+ },
+ {
+ "referenced_type" : "_ZTIDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "function_name" : "android::StopWatch::elapsedTime",
+ "linker_set_key" : "_ZNK7android9StopWatch11elapsedTimeEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::StopWatch::name",
+ "linker_set_key" : "_ZNK7android9StopWatch4nameEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9StopWatchE"
+ }
+ ],
+ "return_type" : "_ZTIPKc",
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::getLocation",
+ "linker_set_key" : "_ZNK7android9Tokenizer11getLocationEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "android::Tokenizer::peekRemainderOfLine",
+ "linker_set_key" : "_ZNK7android9Tokenizer19peekRemainderOfLineEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android9TokenizerE"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "function_name" : "androidCreateRawThreadEtc",
+ "linker_set_key" : "androidCreateRawThreadEtc",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidCreateThread",
+ "linker_set_key" : "androidCreateThread",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidCreateThreadEtc",
+ "linker_set_key" : "androidCreateThreadEtc",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPvE"
+ },
+ {
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPPv"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidGetThreadId",
+ "linker_set_key" : "androidGetThreadId",
+ "return_type" : "_ZTIPv",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidGetThreadPriority",
+ "linker_set_key" : "androidGetThreadPriority",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidSetCreateThreadFunc",
+ "linker_set_key" : "androidSetCreateThreadFunc",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPFiPFiPvES_PKcijPS_E"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidSetThreadName",
+ "linker_set_key" : "androidSetThreadName",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "androidSetThreadPriority",
+ "linker_set_key" : "androidSetThreadPriority",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "function_name" : "strcmp16",
+ "linker_set_key" : "strcmp16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strlen16",
+ "linker_set_key" : "strlen16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strncmp16",
+ "linker_set_key" : "strncmp16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strnlen16",
+ "linker_set_key" : "strnlen16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIj",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strstr16",
+ "linker_set_key" : "strstr16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "strzcmp16",
+ "linker_set_key" : "strzcmp16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "systemTime",
+ "linker_set_key" : "systemTime",
+ "parameters" :
+ [
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "return_type" : "_ZTIx",
+ "source_file" : "system/core/libutils/include/utils/Timers.h"
+ },
+ {
+ "function_name" : "toMillisecondTimeoutDelay",
+ "linker_set_key" : "toMillisecondTimeoutDelay",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIx"
+ },
+ {
+ "referenced_type" : "_ZTIx"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Timers.h"
+ },
+ {
+ "function_name" : "utf16_to_utf8",
+ "linker_set_key" : "utf16_to_utf8",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf16_to_utf8_length",
+ "linker_set_key" : "utf16_to_utf8_length",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf32_from_utf8_at",
+ "linker_set_key" : "utf32_from_utf8_at",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf32_to_utf8",
+ "linker_set_key" : "utf32_to_utf8",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIv",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf32_to_utf8_length",
+ "linker_set_key" : "utf32_to_utf8_length",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKDi"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf8_to_utf16",
+ "linker_set_key" : "utf8_to_utf16",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf8_to_utf16_length",
+ "linker_set_key" : "utf8_to_utf16_length",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "return_type" : "_ZTIi",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "function_name" : "utf8_to_utf16_no_null_terminator",
+ "linker_set_key" : "utf8_to_utf16_no_null_terminator",
+ "parameters" :
+ [
+ {
+ "referenced_type" : "_ZTIPKh"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "referenced_type" : "_ZTIPDs"
+ },
+ {
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "return_type" : "_ZTIPDs",
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ }
+ ],
+ "global_vars" :
+ [
+ {
+ "access" : "private",
+ "linker_set_key" : "_ZN7android7FileMap9mPageSizeE",
+ "name" : "android::FileMap::mPageSize",
+ "referenced_type" : "_ZTIl",
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ }
+ ],
+ "lvalue_reference_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRA1_KDs",
+ "name" : "const char16_t (&)[1]",
+ "referenced_type" : "_ZTIA1_KDs",
+ "self_type" : "_ZTIRA1_KDs",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android10VectorImplE",
+ "name" : "const android::VectorImpl &",
+ "referenced_type" : "_ZTIKN7android10VectorImplE",
+ "self_type" : "_ZTIRKN7android10VectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android16ReferenceRenamerE",
+ "name" : "const android::ReferenceRenamer &",
+ "referenced_type" : "_ZTIKN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIRKN7android16ReferenceRenamerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android16SortedVectorImplE",
+ "name" : "const android::SortedVectorImpl &",
+ "referenced_type" : "_ZTIKN7android16SortedVectorImplE",
+ "self_type" : "_ZTIRKN7android16SortedVectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android28sysprop_change_callback_infoE",
+ "name" : "const android::sysprop_change_callback_info &",
+ "referenced_type" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIRKN7android28sysprop_change_callback_infoE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android2spINS_14LooperCallbackEEE",
+ "name" : "const android::sp<android::LooperCallback> &",
+ "referenced_type" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIRKN7android2spINS_14LooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android2spINS_14MessageHandlerEEE",
+ "name" : "const android::sp<android::MessageHandler> &",
+ "referenced_type" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIRKN7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "const android::sp<android::SimpleLooperCallback> &",
+ "referenced_type" : "_ZTIKN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIRKN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android2spINS_6LooperEEE",
+ "name" : "const android::sp<android::Looper> &",
+ "referenced_type" : "_ZTIKN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIRKN7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android2spINS_6ThreadEEE",
+ "name" : "const android::sp<android::Thread> &",
+ "referenced_type" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIRKN7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE",
+ "name" : "const android::wp<android::MessageHandler> &",
+ "referenced_type" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIRKN7android2wpINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android6Looper15MessageEnvelopeE",
+ "name" : "const android::Looper::MessageEnvelope &",
+ "referenced_type" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIRKN7android6Looper15MessageEnvelopeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android6Looper8ResponseE",
+ "name" : "const android::Looper::Response &",
+ "referenced_type" : "_ZTIKN7android6Looper8ResponseE",
+ "self_type" : "_ZTIRKN7android6Looper8ResponseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "const android::Vector<android::sysprop_change_callback_info> &",
+ "referenced_type" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIRKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android7MessageE",
+ "name" : "const android::Message &",
+ "referenced_type" : "_ZTIKN7android7MessageE",
+ "self_type" : "_ZTIRKN7android7MessageE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android7String8E",
+ "name" : "const android::String8 &",
+ "referenced_type" : "_ZTIKN7android7String8E",
+ "self_type" : "_ZTIRKN7android7String8E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android8String1610StaticDataILj1EEE",
+ "name" : "const android::String16::StaticData<1> &",
+ "referenced_type" : "_ZTIKN7android8String1610StaticDataILj1EEE",
+ "self_type" : "_ZTIRKN7android8String1610StaticDataILj1EEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKN7android8String16E",
+ "name" : "const android::String16 &",
+ "referenced_type" : "_ZTIKN7android8String16E",
+ "self_type" : "_ZTIRKN7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKa",
+ "name" : "const signed char &",
+ "referenced_type" : "_ZTIKa",
+ "self_type" : "_ZTIRKa",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKb",
+ "name" : "const bool &",
+ "referenced_type" : "_ZTIKb",
+ "self_type" : "_ZTIRKb",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKd",
+ "name" : "const double &",
+ "referenced_type" : "_ZTIKd",
+ "self_type" : "_ZTIRKd",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKf",
+ "name" : "const float &",
+ "referenced_type" : "_ZTIKf",
+ "self_type" : "_ZTIRKf",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKh",
+ "name" : "const unsigned char &",
+ "referenced_type" : "_ZTIKh",
+ "self_type" : "_ZTIRKh",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKi",
+ "name" : "const int &",
+ "referenced_type" : "_ZTIKi",
+ "self_type" : "_ZTIRKi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKj",
+ "name" : "const unsigned int &",
+ "referenced_type" : "_ZTIKj",
+ "self_type" : "_ZTIRKj",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKs",
+ "name" : "const short &",
+ "referenced_type" : "_ZTIKs",
+ "self_type" : "_ZTIRKs",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKt",
+ "name" : "const unsigned short &",
+ "referenced_type" : "_ZTIKt",
+ "self_type" : "_ZTIRKt",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKx",
+ "name" : "const long long &",
+ "referenced_type" : "_ZTIKx",
+ "self_type" : "_ZTIRKx",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRKy",
+ "name" : "const unsigned long long &",
+ "referenced_type" : "_ZTIKy",
+ "self_type" : "_ZTIRKy",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android10VectorImplE",
+ "name" : "android::VectorImpl &",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIRN7android10VectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android16SortedVectorImplE",
+ "name" : "android::SortedVectorImpl &",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIRN7android16SortedVectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android2spINS_14LooperCallbackEEE",
+ "name" : "android::sp<android::LooperCallback> &",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIRN7android2spINS_14LooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler> &",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIRN7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback> &",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIRN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper> &",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIRN7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread> &",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIRN7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android5MutexE",
+ "name" : "android::Mutex &",
+ "referenced_type" : "_ZTIN7android5MutexE",
+ "self_type" : "_ZTIRN7android5MutexE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android6Looper8ResponseE",
+ "name" : "android::Looper::Response &",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIRN7android6Looper8ResponseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android6RWLockE",
+ "name" : "android::RWLock &",
+ "referenced_type" : "_ZTIN7android6RWLockE",
+ "self_type" : "_ZTIRN7android6RWLockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::Vector<android::sysprop_change_callback_info> &",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIRN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android7FileMapE",
+ "name" : "android::FileMap &",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIRN7android7FileMapE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android7PrinterE",
+ "name" : "android::Printer &",
+ "referenced_type" : "_ZTIN7android7PrinterE",
+ "self_type" : "_ZTIRN7android7PrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android7String8E",
+ "name" : "android::String8 &",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIRN7android7String8E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRN7android8String16E",
+ "name" : "android::String16 &",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIRN7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRP13native_handle",
+ "name" : "native_handle *&",
+ "referenced_type" : "_ZTIP13native_handle",
+ "self_type" : "_ZTIRP13native_handle",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRPFiiiPvE",
+ "name" : "int (*&)(int, int, void *)",
+ "referenced_type" : "_ZTIPFiiiPvE",
+ "self_type" : "_ZTIRPFiiiPvE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIRb",
+ "name" : "bool &",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIRb",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ }
+ ],
+ "pointer_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP13native_handle",
+ "name" : "native_handle *",
+ "referenced_type" : "_ZTI13native_handle",
+ "self_type" : "_ZTIP13native_handle",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP18android_flex_plane",
+ "name" : "android_flex_plane *",
+ "referenced_type" : "_ZTI18android_flex_plane",
+ "self_type" : "_ZTIP18android_flex_plane",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP3DIR",
+ "name" : "DIR *",
+ "referenced_type" : "_ZTI3DIR",
+ "self_type" : "_ZTIP3DIR",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP7__sFILE",
+ "name" : "__sFILE *",
+ "referenced_type" : "_ZTI7__sFILE",
+ "self_type" : "_ZTIP7__sFILE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIP7log_msg",
+ "name" : "log_msg *",
+ "referenced_type" : "_ZTI7log_msg",
+ "self_type" : "_ZTIP7log_msg",
+ "size" : 4,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPDs",
+ "name" : "char16_t *",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIPDs",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFiPFiPvES_PKcijPS_E",
+ "name" : "int (*)(int (*)(void *), void *, const char *, int, unsigned int, void **)",
+ "referenced_type" : "_ZTIFiPFiPvES_PKcijPS_E",
+ "self_type" : "_ZTIPFiPFiPvES_PKcijPS_E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFiPKvS0_E",
+ "name" : "int (*)(const void *, const void *)",
+ "referenced_type" : "_ZTIFiPKvS0_E",
+ "self_type" : "_ZTIPFiPKvS0_E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFiPKvS0_PvE",
+ "name" : "int (*)(const void *, const void *, void *)",
+ "referenced_type" : "_ZTIFiPKvS0_PvE",
+ "self_type" : "_ZTIPFiPKvS0_PvE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFiPvE",
+ "name" : "int (*)(void *)",
+ "referenced_type" : "_ZTIFiPvE",
+ "self_type" : "_ZTIPFiPvE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFiiiPvE",
+ "name" : "int (*)(int, int, void *)",
+ "referenced_type" : "_ZTIFiiiPvE",
+ "self_type" : "_ZTIPFiiiPvE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPFvvE",
+ "name" : "void (*)()",
+ "referenced_type" : "_ZTIFvvE",
+ "self_type" : "_ZTIPFvvE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/misc.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/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPK7log_msg",
+ "name" : "const log_msg *",
+ "referenced_type" : "_ZTIK7log_msg",
+ "self_type" : "_ZTIPK7log_msg",
+ "size" : 4,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKDi",
+ "name" : "const char32_t *",
+ "referenced_type" : "_ZTIKDi",
+ "self_type" : "_ZTIPKDi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKDs",
+ "name" : "const char16_t *",
+ "referenced_type" : "_ZTIKDs",
+ "self_type" : "_ZTIPKDs",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android10VectorImplE",
+ "name" : "const android::VectorImpl *",
+ "referenced_type" : "_ZTIKN7android10VectorImplE",
+ "self_type" : "_ZTIPKN7android10VectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "const android::LightRefBase<android::NativeHandle> *",
+ "referenced_type" : "_ZTIKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIPKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android12NativeHandleE",
+ "name" : "const android::NativeHandle *",
+ "referenced_type" : "_ZTIKN7android12NativeHandleE",
+ "self_type" : "_ZTIPKN7android12NativeHandleE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android16SortedVectorImplE",
+ "name" : "const android::SortedVectorImpl *",
+ "referenced_type" : "_ZTIKN7android16SortedVectorImplE",
+ "self_type" : "_ZTIPKN7android16SortedVectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android28sysprop_change_callback_infoE",
+ "name" : "const android::sysprop_change_callback_info *",
+ "referenced_type" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIPKN7android28sysprop_change_callback_infoE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android2spINS_14LooperCallbackEEE",
+ "name" : "const android::sp<android::LooperCallback> *",
+ "referenced_type" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIPKN7android2spINS_14LooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android2spINS_14MessageHandlerEEE",
+ "name" : "const android::sp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPKN7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android2spINS_6LooperEEE",
+ "name" : "const android::sp<android::Looper> *",
+ "referenced_type" : "_ZTIKN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIPKN7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android2spINS_6ThreadEEE",
+ "name" : "const android::sp<android::Thread> *",
+ "referenced_type" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIPKN7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android2wpINS_14MessageHandlerEEE",
+ "name" : "const android::wp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPKN7android2wpINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android2wpINS_6ThreadEEE",
+ "name" : "const android::wp<android::Thread> *",
+ "referenced_type" : "_ZTIKN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIPKN7android2wpINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android4base11borrowed_fdE",
+ "name" : "const android::base::borrowed_fd *",
+ "referenced_type" : "_ZTIKN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIPKN7android4base11borrowed_fdE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "const android::base::unique_fd_impl<android::base::DefaultCloser> *",
+ "referenced_type" : "_ZTIKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIPKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6Looper15MessageEnvelopeE",
+ "name" : "const android::Looper::MessageEnvelope *",
+ "referenced_type" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIPKN7android6Looper15MessageEnvelopeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6Looper7RequestE",
+ "name" : "const android::Looper::Request *",
+ "referenced_type" : "_ZTIKN7android6Looper7RequestE",
+ "self_type" : "_ZTIPKN7android6Looper7RequestE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6Looper8ResponseE",
+ "name" : "const android::Looper::Response *",
+ "referenced_type" : "_ZTIKN7android6Looper8ResponseE",
+ "self_type" : "_ZTIPKN7android6Looper8ResponseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6LooperE",
+ "name" : "const android::Looper *",
+ "referenced_type" : "_ZTIKN7android6LooperE",
+ "self_type" : "_ZTIPKN7android6LooperE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6ThreadE",
+ "name" : "const android::Thread *",
+ "referenced_type" : "_ZTIKN7android6ThreadE",
+ "self_type" : "_ZTIPKN7android6ThreadE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "const android::Vector<android::sysprop_change_callback_info> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "const android::Vector<android::Looper::MessageEnvelope> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "const android::Vector<android::Looper::Response> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android6VectorINS_7String8EEE",
+ "name" : "const android::Vector<android::String8> *",
+ "referenced_type" : "_ZTIKN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIPKN7android6VectorINS_7String8EEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android7FileMapE",
+ "name" : "const android::FileMap *",
+ "referenced_type" : "_ZTIKN7android7FileMapE",
+ "self_type" : "_ZTIPKN7android7FileMapE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android7RefBase12weakref_typeE",
+ "name" : "const android::RefBase::weakref_type *",
+ "referenced_type" : "_ZTIKN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIPKN7android7RefBase12weakref_typeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android7RefBaseE",
+ "name" : "const android::RefBase *",
+ "referenced_type" : "_ZTIKN7android7RefBaseE",
+ "self_type" : "_ZTIPKN7android7RefBaseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android7String8E",
+ "name" : "const android::String8 *",
+ "referenced_type" : "_ZTIKN7android7String8E",
+ "self_type" : "_ZTIPKN7android7String8E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android8String16E",
+ "name" : "const android::String16 *",
+ "referenced_type" : "_ZTIKN7android8String16E",
+ "self_type" : "_ZTIPKN7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android9CallStackE",
+ "name" : "const android::CallStack *",
+ "referenced_type" : "_ZTIKN7android9CallStackE",
+ "self_type" : "_ZTIPKN7android9CallStackE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android9StopWatchE",
+ "name" : "const android::StopWatch *",
+ "referenced_type" : "_ZTIKN7android9StopWatchE",
+ "self_type" : "_ZTIPKN7android9StopWatchE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKN7android9TokenizerE",
+ "name" : "const android::Tokenizer *",
+ "referenced_type" : "_ZTIKN7android9TokenizerE",
+ "self_type" : "_ZTIPKN7android9TokenizerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKc",
+ "name" : "const char *",
+ "referenced_type" : "_ZTIKc",
+ "self_type" : "_ZTIPKc",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKh",
+ "name" : "const unsigned char *",
+ "referenced_type" : "_ZTIKh",
+ "self_type" : "_ZTIPKh",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKt",
+ "name" : "const unsigned short *",
+ "referenced_type" : "_ZTIKt",
+ "self_type" : "_ZTIPKt",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/JenkinsHash.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPKv",
+ "name" : "const void *",
+ "referenced_type" : "_ZTIKv",
+ "self_type" : "_ZTIPKv",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android10LogPrinterE",
+ "name" : "android::LogPrinter *",
+ "referenced_type" : "_ZTIN7android10LogPrinterE",
+ "self_type" : "_ZTIPN7android10LogPrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android10VectorImplE",
+ "name" : "android::VectorImpl *",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIPN7android10VectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android11ScopedTraceE",
+ "name" : "android::ScopedTrace *",
+ "referenced_type" : "_ZTIN7android11ScopedTraceE",
+ "self_type" : "_ZTIPN7android11ScopedTraceE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Trace.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "android::LightRefBase<android::NativeHandle> *",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIPN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android12NativeHandleE",
+ "name" : "android::NativeHandle *",
+ "referenced_type" : "_ZTIN7android12NativeHandleE",
+ "self_type" : "_ZTIPN7android12NativeHandleE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android13PrefixPrinterE",
+ "name" : "android::PrefixPrinter *",
+ "referenced_type" : "_ZTIN7android13PrefixPrinterE",
+ "self_type" : "_ZTIPN7android13PrefixPrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android14LooperCallbackE",
+ "name" : "android::LooperCallback *",
+ "referenced_type" : "_ZTIN7android14LooperCallbackE",
+ "self_type" : "_ZTIPN7android14LooperCallbackE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android14MessageHandlerE",
+ "name" : "android::MessageHandler *",
+ "referenced_type" : "_ZTIN7android14MessageHandlerE",
+ "self_type" : "_ZTIPN7android14MessageHandlerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android14StaticString16ILj1EEE",
+ "name" : "android::StaticString16<1> *",
+ "referenced_type" : "_ZTIN7android14StaticString16ILj1EEE",
+ "self_type" : "_ZTIPN7android14StaticString16ILj1EEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android14String8PrinterE",
+ "name" : "android::String8Printer *",
+ "referenced_type" : "_ZTIN7android14String8PrinterE",
+ "self_type" : "_ZTIPN7android14String8PrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android16ReferenceRenamerE",
+ "name" : "android::ReferenceRenamer *",
+ "referenced_type" : "_ZTIN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIPN7android16ReferenceRenamerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android16SortedVectorImplE",
+ "name" : "android::SortedVectorImpl *",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIPN7android16SortedVectorImplE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android18WeakMessageHandlerE",
+ "name" : "android::WeakMessageHandler *",
+ "referenced_type" : "_ZTIN7android18WeakMessageHandlerE",
+ "self_type" : "_ZTIPN7android18WeakMessageHandlerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android19VirtualLightRefBaseE",
+ "name" : "android::VirtualLightRefBase *",
+ "referenced_type" : "_ZTIN7android19VirtualLightRefBaseE",
+ "self_type" : "_ZTIPN7android19VirtualLightRefBaseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android20SimpleLooperCallbackE",
+ "name" : "android::SimpleLooperCallback *",
+ "referenced_type" : "_ZTIN7android20SimpleLooperCallbackE",
+ "self_type" : "_ZTIPN7android20SimpleLooperCallbackE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android28sysprop_change_callback_infoE",
+ "name" : "android::sysprop_change_callback_info *",
+ "referenced_type" : "_ZTIN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIPN7android28sysprop_change_callback_infoE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2spINS_12NativeHandleEEE",
+ "name" : "android::sp<android::NativeHandle> *",
+ "referenced_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "self_type" : "_ZTIPN7android2spINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2spINS_14LooperCallbackEEE",
+ "name" : "android::sp<android::LooperCallback> *",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIPN7android2spINS_14LooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPN7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback> *",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIPN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper> *",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIPN7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread> *",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIPN7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2wpINS_14MessageHandlerEEE",
+ "name" : "android::wp<android::MessageHandler> *",
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIPN7android2wpINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android2wpINS_6ThreadEEE",
+ "name" : "android::wp<android::Thread> *",
+ "referenced_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIPN7android2wpINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android4base11borrowed_fdE",
+ "name" : "android::base::borrowed_fd *",
+ "referenced_type" : "_ZTIN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIPN7android4base11borrowed_fdE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "android::base::unique_fd_impl<android::base::DefaultCloser> *",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIPN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android5Mutex8AutolockE",
+ "name" : "android::Mutex::Autolock *",
+ "referenced_type" : "_ZTIN7android5Mutex8AutolockE",
+ "self_type" : "_ZTIPN7android5Mutex8AutolockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android5MutexE",
+ "name" : "android::Mutex *",
+ "referenced_type" : "_ZTIN7android5MutexE",
+ "self_type" : "_ZTIPN7android5MutexE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6Looper15MessageEnvelopeE",
+ "name" : "android::Looper::MessageEnvelope *",
+ "referenced_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIPN7android6Looper15MessageEnvelopeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6Looper8ResponseE",
+ "name" : "android::Looper::Response *",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIPN7android6Looper8ResponseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6LooperE",
+ "name" : "android::Looper *",
+ "referenced_type" : "_ZTIN7android6LooperE",
+ "self_type" : "_ZTIPN7android6LooperE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6RWLock9AutoRLockE",
+ "name" : "android::RWLock::AutoRLock *",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoRLockE",
+ "self_type" : "_ZTIPN7android6RWLock9AutoRLockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6RWLock9AutoWLockE",
+ "name" : "android::RWLock::AutoWLock *",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoWLockE",
+ "self_type" : "_ZTIPN7android6RWLock9AutoWLockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6RWLockE",
+ "name" : "android::RWLock *",
+ "referenced_type" : "_ZTIN7android6RWLockE",
+ "self_type" : "_ZTIPN7android6RWLockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6ThreadE",
+ "name" : "android::Thread *",
+ "referenced_type" : "_ZTIN7android6ThreadE",
+ "self_type" : "_ZTIPN7android6ThreadE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::Vector<android::sysprop_change_callback_info> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIPN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::Vector<android::Looper::MessageEnvelope> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIPN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "android::Vector<android::Looper::Response> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIPN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android6VectorINS_7String8EEE",
+ "name" : "android::Vector<android::String8> *",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIPN7android6VectorINS_7String8EEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7FileMapE",
+ "name" : "android::FileMap *",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIPN7android7FileMapE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7MessageE",
+ "name" : "android::Message *",
+ "referenced_type" : "_ZTIN7android7MessageE",
+ "self_type" : "_ZTIPN7android7MessageE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7PrinterE",
+ "name" : "android::Printer *",
+ "referenced_type" : "_ZTIN7android7PrinterE",
+ "self_type" : "_ZTIPN7android7PrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7RefBase12weakref_implE",
+ "name" : "android::RefBase::weakref_impl *",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_implE",
+ "self_type" : "_ZTIPN7android7RefBase12weakref_implE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "name" : "android::RefBase::weakref_type *",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIPN7android7RefBase12weakref_typeE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7RefBaseE",
+ "name" : "android::RefBase *",
+ "referenced_type" : "_ZTIN7android7RefBaseE",
+ "self_type" : "_ZTIPN7android7RefBaseE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android7String8E",
+ "name" : "android::String8 *",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIPN7android7String8E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android8String1610StaticDataILj1EEE",
+ "name" : "android::String16::StaticData<1> *",
+ "referenced_type" : "_ZTIN7android8String1610StaticDataILj1EEE",
+ "self_type" : "_ZTIPN7android8String1610StaticDataILj1EEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android8String16E",
+ "name" : "android::String16 *",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIPN7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android9CallStack12StackDeleterE",
+ "name" : "android::CallStack::StackDeleter *",
+ "referenced_type" : "_ZTIN7android9CallStack12StackDeleterE",
+ "self_type" : "_ZTIPN7android9CallStack12StackDeleterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android9CallStackE",
+ "name" : "android::CallStack *",
+ "referenced_type" : "_ZTIN7android9CallStackE",
+ "self_type" : "_ZTIPN7android9CallStackE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android9ConditionE",
+ "name" : "android::Condition *",
+ "referenced_type" : "_ZTIN7android9ConditionE",
+ "self_type" : "_ZTIPN7android9ConditionE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Condition.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android9FdPrinterE",
+ "name" : "android::FdPrinter *",
+ "referenced_type" : "_ZTIN7android9FdPrinterE",
+ "self_type" : "_ZTIPN7android9FdPrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android9StopWatchE",
+ "name" : "android::StopWatch *",
+ "referenced_type" : "_ZTIN7android9StopWatchE",
+ "self_type" : "_ZTIPN7android9StopWatchE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPN7android9TokenizerE",
+ "name" : "android::Tokenizer *",
+ "referenced_type" : "_ZTIN7android9TokenizerE",
+ "self_type" : "_ZTIPN7android9TokenizerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPPN7android9TokenizerE",
+ "name" : "android::Tokenizer **",
+ "referenced_type" : "_ZTIPN7android9TokenizerE",
+ "self_type" : "_ZTIPPN7android9TokenizerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPPv",
+ "name" : "void **",
+ "referenced_type" : "_ZTIPv",
+ "self_type" : "_ZTIPPv",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/AndroidThreads.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPc",
+ "name" : "char *",
+ "referenced_type" : "_ZTIc",
+ "self_type" : "_ZTIPc",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPh",
+ "name" : "unsigned char *",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIPh",
+ "size" : 4,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPi",
+ "name" : "int *",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIPi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPj",
+ "name" : "unsigned int *",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIPj",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Unicode.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIPv",
+ "name" : "void *",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIPv",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ }
+ ],
+ "qualified_types" :
+ [
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIA1_KDs",
+ "name" : "const char16_t[1]",
+ "referenced_type" : "_ZTIA1_Ds",
+ "self_type" : "_ZTIA1_KDs",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "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/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIK7log_msg",
+ "name" : "const log_msg",
+ "referenced_type" : "_ZTI7log_msg",
+ "self_type" : "_ZTIK7log_msg",
+ "size" : 5124,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKDi",
+ "name" : "const char32_t",
+ "referenced_type" : "_ZTIDi",
+ "self_type" : "_ZTIKDi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKDs",
+ "name" : "const char16_t",
+ "referenced_type" : "_ZTIDs",
+ "self_type" : "_ZTIKDs",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android10VectorImplE",
+ "name" : "const android::VectorImpl",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIKN7android10VectorImplE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "const android::LightRefBase<android::NativeHandle>",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIKN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android12NativeHandleE",
+ "name" : "const android::NativeHandle",
+ "referenced_type" : "_ZTIN7android12NativeHandleE",
+ "self_type" : "_ZTIKN7android12NativeHandleE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android16ReferenceRenamerE",
+ "name" : "const android::ReferenceRenamer",
+ "referenced_type" : "_ZTIN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIKN7android16ReferenceRenamerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android16SortedVectorImplE",
+ "name" : "const android::SortedVectorImpl",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIKN7android16SortedVectorImplE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "name" : "const android::sysprop_change_callback_info",
+ "referenced_type" : "_ZTIN7android28sysprop_change_callback_infoE",
+ "self_type" : "_ZTIKN7android28sysprop_change_callback_infoE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "name" : "const android::sp<android::LooperCallback>",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIKN7android2spINS_14LooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "name" : "const android::sp<android::MessageHandler>",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIKN7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "const android::sp<android::SimpleLooperCallback>",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIKN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_6LooperEEE",
+ "name" : "const android::sp<android::Looper>",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIKN7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "name" : "const android::sp<android::Thread>",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIKN7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "name" : "const android::wp<android::MessageHandler>",
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIKN7android2wpINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android2wpINS_6ThreadEEE",
+ "name" : "const android::wp<android::Thread>",
+ "referenced_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIKN7android2wpINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android4base11borrowed_fdE",
+ "name" : "const android::base::borrowed_fd",
+ "referenced_type" : "_ZTIN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIKN7android4base11borrowed_fdE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "const android::base::unique_fd_impl<android::base::DefaultCloser>",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIKN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "name" : "const android::Looper::MessageEnvelope",
+ "referenced_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIKN7android6Looper15MessageEnvelopeE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6Looper7RequestE",
+ "name" : "const android::Looper::Request",
+ "referenced_type" : "_ZTIN7android6Looper7RequestE",
+ "self_type" : "_ZTIKN7android6Looper7RequestE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6Looper8ResponseE",
+ "name" : "const android::Looper::Response",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIKN7android6Looper8ResponseE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6LooperE",
+ "name" : "const android::Looper",
+ "referenced_type" : "_ZTIN7android6LooperE",
+ "self_type" : "_ZTIKN7android6LooperE",
+ "size" : 136,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6ThreadE",
+ "name" : "const android::Thread",
+ "referenced_type" : "_ZTIN7android6ThreadE",
+ "self_type" : "_ZTIKN7android6ThreadE",
+ "size" : 44,
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "const android::Vector<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIKN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "const android::Vector<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIKN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "const android::Vector<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIKN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android6VectorINS_7String8EEE",
+ "name" : "const android::Vector<android::String8>",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIKN7android6VectorINS_7String8EEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7FileMapE",
+ "name" : "const android::FileMap",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIKN7android7FileMapE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7MessageE",
+ "name" : "const android::Message",
+ "referenced_type" : "_ZTIN7android7MessageE",
+ "self_type" : "_ZTIKN7android7MessageE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7RefBase12weakref_typeE",
+ "name" : "const android::RefBase::weakref_type",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIKN7android7RefBase12weakref_typeE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7RefBaseE",
+ "name" : "const android::RefBase",
+ "referenced_type" : "_ZTIN7android7RefBaseE",
+ "self_type" : "_ZTIKN7android7RefBaseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android7String8E",
+ "name" : "const android::String8",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIKN7android7String8E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android8String1610StaticDataILj1EEE",
+ "name" : "const android::String16::StaticData<1>",
+ "referenced_type" : "_ZTIN7android8String1610StaticDataILj1EEE",
+ "self_type" : "_ZTIKN7android8String1610StaticDataILj1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android8String16E",
+ "name" : "const android::String16",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIKN7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android9CallStackE",
+ "name" : "const android::CallStack",
+ "referenced_type" : "_ZTIN7android9CallStackE",
+ "self_type" : "_ZTIKN7android9CallStackE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android9StopWatchE",
+ "name" : "const android::StopWatch",
+ "referenced_type" : "_ZTIN7android9StopWatchE",
+ "self_type" : "_ZTIKN7android9StopWatchE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKN7android9TokenizerE",
+ "name" : "const android::Tokenizer",
+ "referenced_type" : "_ZTIN7android9TokenizerE",
+ "self_type" : "_ZTIKN7android9TokenizerE",
+ "size" : 28,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKPKc",
+ "name" : "const char *const",
+ "referenced_type" : "_ZTIPKc",
+ "self_type" : "_ZTIKPKc",
+ "size" : 4,
+ "source_file" : "system/core/libprocessgroup/include/processgroup/processgroup.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKPN7android7RefBase12weakref_implE",
+ "name" : "android::RefBase::weakref_impl *const",
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_implE",
+ "self_type" : "_ZTIKPN7android7RefBase12weakref_implE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKa",
+ "name" : "const signed char",
+ "referenced_type" : "_ZTIa",
+ "self_type" : "_ZTIKa",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKb",
+ "name" : "const bool",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIKb",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.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/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKd",
+ "name" : "const double",
+ "referenced_type" : "_ZTId",
+ "self_type" : "_ZTIKd",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKf",
+ "name" : "const float",
+ "referenced_type" : "_ZTIf",
+ "self_type" : "_ZTIKf",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 1,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKh",
+ "name" : "const unsigned char",
+ "referenced_type" : "_ZTIh",
+ "self_type" : "_ZTIKh",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKi",
+ "name" : "const int",
+ "referenced_type" : "_ZTIi",
+ "self_type" : "_ZTIKi",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 4,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKj",
+ "name" : "const unsigned int",
+ "referenced_type" : "_ZTIj",
+ "self_type" : "_ZTIKj",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKs",
+ "name" : "const short",
+ "referenced_type" : "_ZTIs",
+ "self_type" : "_ZTIKs",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 2,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKt",
+ "name" : "const unsigned short",
+ "referenced_type" : "_ZTIt",
+ "self_type" : "_ZTIKt",
+ "size" : 2,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKv",
+ "name" : "const void",
+ "referenced_type" : "_ZTIv",
+ "self_type" : "_ZTIKv",
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKx",
+ "name" : "const long long",
+ "referenced_type" : "_ZTIx",
+ "self_type" : "_ZTIKx",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 8,
+ "is_const" : true,
+ "linker_set_key" : "_ZTIKy",
+ "name" : "const unsigned long long",
+ "referenced_type" : "_ZTIy",
+ "self_type" : "_ZTIKy",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h"
+ },
+ {
+ "alignment" : 1,
+ "is_volatile" : true,
+ "linker_set_key" : "_ZTIVb",
+ "name" : "volatile bool",
+ "referenced_type" : "_ZTIb",
+ "self_type" : "_ZTIVb",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/Thread.h"
+ }
+ ],
+ "record_types" :
+ [
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "len",
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "field_name" : "hdr_size",
+ "field_offset" : 16,
+ "referenced_type" : "_ZTIt"
+ },
+ {
+ "field_name" : "pid",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "tid",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "sec",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "nsec",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "lid",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "uid",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "linker_set_key" : "_ZTI12logger_entry",
+ "name" : "logger_entry",
+ "referenced_type" : "_ZTI12logger_entry",
+ "self_type" : "_ZTI12logger_entry",
+ "size" : 28,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "y",
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "field_name" : "cb",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "field_name" : "cr",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "field_name" : "ystride",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "cstride",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "chroma_step",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "reserved",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIA8_j"
+ }
+ ],
+ "linker_set_key" : "_ZTI13android_ycbcr",
+ "name" : "android_ycbcr",
+ "referenced_type" : "_ZTI13android_ycbcr",
+ "self_type" : "_ZTI13android_ycbcr",
+ "size" : 56,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "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_outside_system/cutils/native_handle.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "x",
+ "referenced_type" : "_ZTIf"
+ },
+ {
+ "field_name" : "y",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "linker_set_key" : "_ZTI16android_xy_color",
+ "name" : "android_xy_color",
+ "referenced_type" : "_ZTI16android_xy_color",
+ "self_type" : "_ZTI16android_xy_color",
+ "size" : 8,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "top_left",
+ "referenced_type" : "_ZTIPh"
+ },
+ {
+ "field_name" : "component",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTI22android_flex_component"
+ },
+ {
+ "field_name" : "bits_per_component",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "bits_used",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "h_increment",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "v_increment",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "h_subsampling",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "v_subsampling",
+ "field_offset" : 224,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTI18android_flex_plane",
+ "name" : "android_flex_plane",
+ "referenced_type" : "_ZTI18android_flex_plane",
+ "self_type" : "_ZTI18android_flex_plane",
+ "size" : 32,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "format",
+ "referenced_type" : "_ZTI19android_flex_format"
+ },
+ {
+ "field_name" : "num_planes",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "planes",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIP18android_flex_plane"
+ }
+ ],
+ "linker_set_key" : "_ZTI19android_flex_layout",
+ "name" : "android_flex_layout",
+ "referenced_type" : "_ZTI19android_flex_layout",
+ "self_type" : "_ZTI19android_flex_layout",
+ "size" : 12,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "num_points",
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "reserved",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIA8_j"
+ },
+ {
+ "field_name" : "xyzc_points",
+ "field_offset" : 288,
+ "referenced_type" : "_ZTIA_f"
+ }
+ ],
+ "linker_set_key" : "_ZTI20android_depth_points",
+ "name" : "android_depth_points",
+ "referenced_type" : "_ZTI20android_depth_points",
+ "self_type" : "_ZTI20android_depth_points",
+ "size" : 36,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "struct_size",
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "buffer_id",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "priority",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "tag",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "field_name" : "file",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "field_name" : "line",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "message",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTI21__android_log_message",
+ "name" : "__android_log_message",
+ "referenced_type" : "_ZTI21__android_log_message",
+ "self_type" : "_ZTI21__android_log_message",
+ "size" : 28,
+ "source_file" : "system/logging/liblog/include_vndk/android/log.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "maxContentLightLevel",
+ "referenced_type" : "_ZTIf"
+ },
+ {
+ "field_name" : "maxFrameAverageLightLevel",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "linker_set_key" : "_ZTI25android_cta861_3_metadata",
+ "name" : "android_cta861_3_metadata",
+ "referenced_type" : "_ZTI25android_cta861_3_metadata",
+ "self_type" : "_ZTI25android_cta861_3_metadata",
+ "size" : 8,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "displayPrimaryRed",
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "displayPrimaryGreen",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "displayPrimaryBlue",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "whitePoint",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTI16android_xy_color"
+ },
+ {
+ "field_name" : "maxLuminance",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIf"
+ },
+ {
+ "field_name" : "minLuminance",
+ "field_offset" : 288,
+ "referenced_type" : "_ZTIf"
+ }
+ ],
+ "linker_set_key" : "_ZTI26android_smpte2086_metadata",
+ "name" : "android_smpte2086_metadata",
+ "referenced_type" : "_ZTI26android_smpte2086_metadata",
+ "self_type" : "_ZTI26android_smpte2086_metadata",
+ "size" : 40,
+ "source_file" : "system/core/libsystem/include/system/graphics.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "referenced_type" : "_ZTIN7log_msgUt_E"
+ }
+ ],
+ "linker_set_key" : "_ZTI7log_msg",
+ "name" : "log_msg",
+ "referenced_type" : "_ZTI7log_msg",
+ "self_type" : "_ZTI7log_msg",
+ "size" : 5124,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ },
+ {
+ "alignment" : 1,
+ "fields" :
+ [
+ {
+ "field_name" : "tv_sec",
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "field_name" : "tv_nsec",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "linker_set_key" : "_ZTI8log_time",
+ "name" : "log_time",
+ "referenced_type" : "_ZTI8log_time",
+ "self_type" : "_ZTI8log_time",
+ "size" : 8,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_time.h"
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLogTag",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPriority",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTI19android_LogPriority"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mIgnoreBlankLines",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android10LogPrinterE",
+ "name" : "android::LogPrinter",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android10LogPrinterE",
+ "self_type" : "_ZTIN7android10LogPrinterE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android10LogPrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android10LogPrinter9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10LogPrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10LogPrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mStorage",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mCount",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mFlags",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIKj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mItemSize",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIKj"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android10VectorImplE",
+ "name" : "android::VectorImpl",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android10VectorImplE",
+ "self_type" : "_ZTIN7android10VectorImplE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android10VectorImplE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10VectorImplD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android10VectorImplD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl12do_constructEPvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl10do_destroyEPvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl7do_copyEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl8do_splatEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl15do_move_forwardEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl16do_move_backwardEPvPKvj"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mTag",
+ "referenced_type" : "_ZTIy"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android11ScopedTraceE",
+ "name" : "android::ScopedTrace",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android11ScopedTraceE",
+ "self_type" : "_ZTIN7android11ScopedTraceE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/Trace.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCount",
+ "referenced_type" : "_ZTINSt3__16atomicIiEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "name" : "android::LightRefBase<android::NativeHandle>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "self_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android12NativeHandleE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCount",
+ "referenced_type" : "_ZTINSt3__16atomicIiEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE",
+ "name" : "android::LightRefBase<android::VirtualLightRefBase>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE",
+ "self_type" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android19VirtualLightRefBaseE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_12NativeHandleEEE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mHandle",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIP13native_handle"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mOwnsHandle",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIb"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android12NativeHandleE",
+ "name" : "android::NativeHandle",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android12NativeHandleE",
+ "self_type" : "_ZTIN7android12NativeHandleE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/NativeHandle.h"
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mPrinter",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIRN7android7PrinterE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android13PrefixPrinterE",
+ "name" : "android::PrefixPrinter",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android13PrefixPrinterE",
+ "self_type" : "_ZTIN7android13PrefixPrinterE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android13PrefixPrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android13PrefixPrinter9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android13PrefixPrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android13PrefixPrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_pointer<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_pointer<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEEE",
+ "name" : "android::trait_pointer<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android13trait_pointerINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "is_virtual" : true,
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14LooperCallbackE",
+ "name" : "android::LooperCallback",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14LooperCallbackE",
+ "self_type" : "_ZTIN7android14LooperCallbackE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 4,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14LooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14LooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14LooperCallbackD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android14LooperCallback11handleEventEiiPv"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -4,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -4,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14LooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android14LooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android14LooperCallbackD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "is_virtual" : true,
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14MessageHandlerE",
+ "name" : "android::MessageHandler",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14MessageHandlerE",
+ "self_type" : "_ZTIN7android14MessageHandlerE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 4,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14MessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14MessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14MessageHandlerD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android14MessageHandler13handleMessageERKNS_7MessageE"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -4,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -4,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14MessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android14MessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android14MessageHandlerD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android14ReferenceMoverE",
+ "name" : "android::ReferenceMover",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14ReferenceMoverE",
+ "self_type" : "_ZTIN7android14ReferenceMoverE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android8String16E"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mData",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIKN7android8String1610StaticDataILj1EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14StaticString16ILj1EEE",
+ "name" : "android::StaticString16<1>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14StaticString16ILj1EEE",
+ "self_type" : "_ZTIN7android14StaticString16ILj1EEE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mTarget",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android14String8PrinterE",
+ "name" : "android::String8Printer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android14String8PrinterE",
+ "self_type" : "_ZTIN7android14String8PrinterE",
+ "size" : 12,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android14String8PrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android14String8Printer9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14String8PrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android14String8PrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIN7android16ReferenceRenamerE",
+ "name" : "android::ReferenceRenamer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android16ReferenceRenamerE",
+ "self_type" : "_ZTIN7android16ReferenceRenamerE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android16ReferenceRenamerE"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android16ReferenceRenamerclEj"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16SortedVectorImplE",
+ "name" : "android::SortedVectorImpl",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android16SortedVectorImplE",
+ "self_type" : "_ZTIN7android16SortedVectorImplE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/VectorImpl.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android16SortedVectorImplE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android16SortedVectorImplD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android16SortedVectorImplD0Ev"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl12do_constructEPvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl10do_destroyEPvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl7do_copyEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl8do_splatEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl15do_move_forwardEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android10VectorImpl16do_move_backwardEPvPKvj"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZNK7android16SortedVectorImpl10do_compareEPKvS2_"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTINSt3__117integral_constantIbLb0EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16use_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::use_trivial_move<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android16use_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android16use_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTINSt3__117integral_constantIbLb0EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16use_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::use_trivial_move<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android16use_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android16use_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTINSt3__117integral_constantIbLb0EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android16use_trivial_moveINS_6Looper8ResponseEEE",
+ "name" : "android::use_trivial_move<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android16use_trivial_moveINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android16use_trivial_moveINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android14MessageHandlerE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mHandler",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android18WeakMessageHandlerE",
+ "name" : "android::WeakMessageHandler",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android18WeakMessageHandlerE",
+ "self_type" : "_ZTIN7android18WeakMessageHandlerE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 12,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android18WeakMessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android18WeakMessageHandler13handleMessageERKNS_7MessageE"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -12,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -12,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android18WeakMessageHandlerE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android18WeakMessageHandlerD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android18WeakMessageHandlerD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_copy<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_copy<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_copy<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIbEE",
+ "name" : "android::trait_trivial_copy<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIcEE",
+ "name" : "android::trait_trivial_copy<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIdEE",
+ "name" : "android::trait_trivial_copy<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIfEE",
+ "name" : "android::trait_trivial_copy<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIhEE",
+ "name" : "android::trait_trivial_copy<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIiEE",
+ "name" : "android::trait_trivial_copy<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIjEE",
+ "name" : "android::trait_trivial_copy<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIlEE",
+ "name" : "android::trait_trivial_copy<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyImEE",
+ "name" : "android::trait_trivial_copy<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIsEE",
+ "name" : "android::trait_trivial_copy<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyItEE",
+ "name" : "android::trait_trivial_copy<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIvEE",
+ "name" : "android::trait_trivial_copy<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIxEE",
+ "name" : "android::trait_trivial_copy<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_copyIyEE",
+ "name" : "android::trait_trivial_copy<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_copyIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_copyIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_ctor<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_ctor<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_ctor<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIbEE",
+ "name" : "android::trait_trivial_ctor<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIcEE",
+ "name" : "android::trait_trivial_ctor<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIdEE",
+ "name" : "android::trait_trivial_ctor<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIfEE",
+ "name" : "android::trait_trivial_ctor<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIhEE",
+ "name" : "android::trait_trivial_ctor<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIiEE",
+ "name" : "android::trait_trivial_ctor<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIjEE",
+ "name" : "android::trait_trivial_ctor<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIlEE",
+ "name" : "android::trait_trivial_ctor<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorImEE",
+ "name" : "android::trait_trivial_ctor<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIsEE",
+ "name" : "android::trait_trivial_ctor<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorItEE",
+ "name" : "android::trait_trivial_ctor<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIvEE",
+ "name" : "android::trait_trivial_ctor<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIxEE",
+ "name" : "android::trait_trivial_ctor<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_ctorIyEE",
+ "name" : "android::trait_trivial_ctor<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_ctorIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_ctorIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_dtor<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_dtor<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_dtor<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIbEE",
+ "name" : "android::trait_trivial_dtor<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIcEE",
+ "name" : "android::trait_trivial_dtor<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIdEE",
+ "name" : "android::trait_trivial_dtor<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIfEE",
+ "name" : "android::trait_trivial_dtor<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIhEE",
+ "name" : "android::trait_trivial_dtor<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIiEE",
+ "name" : "android::trait_trivial_dtor<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIjEE",
+ "name" : "android::trait_trivial_dtor<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIlEE",
+ "name" : "android::trait_trivial_dtor<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorImEE",
+ "name" : "android::trait_trivial_dtor<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIsEE",
+ "name" : "android::trait_trivial_dtor<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorItEE",
+ "name" : "android::trait_trivial_dtor<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIvEE",
+ "name" : "android::trait_trivial_dtor<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIxEE",
+ "name" : "android::trait_trivial_dtor<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_dtorIyEE",
+ "name" : "android::trait_trivial_dtor<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_dtorIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_dtorIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::trait_trivial_move<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::trait_trivial_move<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEEE",
+ "name" : "android::trait_trivial_move<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_7String8EEE",
+ "name" : "android::trait_trivial_move<android::String8>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_7String8EEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/String8.h",
+ "template_args" :
+ [
+ "_ZTIN7android7String8E"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveINS_8String16EEE",
+ "name" : "android::trait_trivial_move<android::String16>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveINS_8String16EEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/String16.h",
+ "template_args" :
+ [
+ "_ZTIN7android8String16E"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIbEE",
+ "name" : "android::trait_trivial_move<bool>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIbEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIbEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIb"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIcEE",
+ "name" : "android::trait_trivial_move<char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIcEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIcEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIc"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIdEE",
+ "name" : "android::trait_trivial_move<double>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIdEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIdEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTId"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIfEE",
+ "name" : "android::trait_trivial_move<float>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIfEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIfEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIf"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIhEE",
+ "name" : "android::trait_trivial_move<unsigned char>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIhEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIhEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIh"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIiEE",
+ "name" : "android::trait_trivial_move<int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIiEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIiEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIi"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIjEE",
+ "name" : "android::trait_trivial_move<unsigned int>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIjEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIjEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIj"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIlEE",
+ "name" : "android::trait_trivial_move<long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIlEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIlEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIl"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveImEE",
+ "name" : "android::trait_trivial_move<unsigned long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveImEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveImEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIm"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIsEE",
+ "name" : "android::trait_trivial_move<short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIsEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIsEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIs"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveItEE",
+ "name" : "android::trait_trivial_move<unsigned short>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveItEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveItEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIt"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIvEE",
+ "name" : "android::trait_trivial_move<void>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIvEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIvEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIv"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIxEE",
+ "name" : "android::trait_trivial_move<long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIxEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIxEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIx"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android18trait_trivial_moveIyEE",
+ "name" : "android::trait_trivial_move<unsigned long long>",
+ "referenced_type" : "_ZTIN7android18trait_trivial_moveIyEE",
+ "self_type" : "_ZTIN7android18trait_trivial_moveIyEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIy"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android12LightRefBaseINS_19VirtualLightRefBaseEEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android19VirtualLightRefBaseE",
+ "name" : "android::VirtualLightRefBase",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android19VirtualLightRefBaseE",
+ "self_type" : "_ZTIN7android19VirtualLightRefBaseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/LightRefBase.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android19VirtualLightRefBaseE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android19VirtualLightRefBaseD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android19VirtualLightRefBaseD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android14LooperCallbackE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCallback",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPFiiiPvE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android20SimpleLooperCallbackE",
+ "name" : "android::SimpleLooperCallback",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android20SimpleLooperCallbackE",
+ "self_type" : "_ZTIN7android20SimpleLooperCallbackE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 8,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android20SimpleLooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android20SimpleLooperCallback11handleEventEiiPv"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -8,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -8,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android20SimpleLooperCallbackE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android20SimpleLooperCallbackD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android20SimpleLooperCallbackD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android12NativeHandleE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "name" : "android::sp<android::NativeHandle>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "self_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android12NativeHandleE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android14LooperCallbackE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "name" : "android::sp<android::LooperCallback>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "self_type" : "_ZTIN7android2spINS_14LooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android14LooperCallbackE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android14MessageHandlerE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android20SimpleLooperCallbackE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android20SimpleLooperCallbackE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android6LooperE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android6LooperE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h",
+ "template_args" :
+ [
+ "_ZTIN7android6ThreadE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android14MessageHandlerE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "m_refs",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "name" : "android::wp<android::MessageHandler>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "self_type" : "_ZTIN7android2wpINS_14MessageHandlerEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android14MessageHandlerE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "m_ptr",
+ "referenced_type" : "_ZTIPN7android6ThreadE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "m_refs",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPN7android7RefBase12weakref_typeE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "name" : "android::wp<android::Thread>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "self_type" : "_ZTIN7android2wpINS_6ThreadEEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "template_args" :
+ [
+ "_ZTIN7android6ThreadE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "fd_",
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android4base11borrowed_fdE",
+ "name" : "android::base::borrowed_fd",
+ "referenced_type" : "_ZTIN7android4base11borrowed_fdE",
+ "self_type" : "_ZTIN7android4base11borrowed_fdE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android4base13DefaultCloserE",
+ "name" : "android::base::DefaultCloser",
+ "referenced_type" : "_ZTIN7android4base13DefaultCloserE",
+ "self_type" : "_ZTIN7android4base13DefaultCloserE",
+ "size" : 1,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "fd_",
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "android::base::unique_fd_impl<android::base::DefaultCloser>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h",
+ "template_args" :
+ [
+ "_ZTIN7android4base13DefaultCloserE"
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "referenced_type" : "_ZTIRN7android5MutexE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android5Mutex8AutolockE",
+ "name" : "android::Mutex::Autolock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android5Mutex8AutolockE",
+ "self_type" : "_ZTIN7android5Mutex8AutolockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mMutex",
+ "referenced_type" : "_ZTI15pthread_mutex_t"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android5MutexE",
+ "name" : "android::Mutex",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android5MutexE",
+ "self_type" : "_ZTIN7android5MutexE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Mutex.h"
+ },
+ {
+ "access" : "private",
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "uptime",
+ "referenced_type" : "_ZTIx"
+ },
+ {
+ "field_name" : "handler",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE"
+ },
+ {
+ "field_name" : "message",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIN7android7MessageE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "name" : "android::Looper::MessageEnvelope",
+ "referenced_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "self_type" : "_ZTIN7android6Looper15MessageEnvelopeE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "fd",
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "ident",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "events",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "callback",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIN7android2spINS_14LooperCallbackEEE"
+ },
+ {
+ "field_name" : "data",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIPv"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper7RequestE",
+ "name" : "android::Looper::Request",
+ "referenced_type" : "_ZTIN7android6Looper7RequestE",
+ "self_type" : "_ZTIN7android6Looper7RequestE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "access" : "private",
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "field_name" : "seq",
+ "referenced_type" : "_ZTIy"
+ },
+ {
+ "field_name" : "events",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "field_name" : "request",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIN7android6Looper7RequestE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6Looper8ResponseE",
+ "name" : "android::Looper::Response",
+ "referenced_type" : "_ZTIN7android6Looper8ResponseE",
+ "self_type" : "_ZTIN7android6Looper8ResponseE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 8,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mAllowNonCallbacks",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIKb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mWakeEventFd",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIN7android5MutexE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mMessageEnvelopes",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mSendingMessage",
+ "field_offset" : 320,
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPolling",
+ "field_offset" : 328,
+ "referenced_type" : "_ZTIVb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mEpollFd",
+ "field_offset" : 352,
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mEpollRebuildRequired",
+ "field_offset" : 384,
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mRequests",
+ "field_offset" : 416,
+ "referenced_type" : "_ZTINSt3__113unordered_mapIyN7android6Looper7RequestENS_4hashIyEENS_8equal_toIyEENS_9allocatorINS_4pairIKyS3_EEEEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mSequenceNumberByFd",
+ "field_offset" : 576,
+ "referenced_type" : "_ZTINSt3__113unordered_mapIiyNS_4hashIiEENS_8equal_toIiEENS_9allocatorINS_4pairIKiyEEEEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mNextRequestSeq",
+ "field_offset" : 768,
+ "referenced_type" : "_ZTIy"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mResponses",
+ "field_offset" : 832,
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mResponseIndex",
+ "field_offset" : 992,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mNextMessageUptime",
+ "field_offset" : 1024,
+ "referenced_type" : "_ZTIx"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6LooperE",
+ "name" : "android::Looper",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6LooperE",
+ "self_type" : "_ZTIN7android6LooperE",
+ "size" : 136,
+ "source_file" : "system/core/libutils/include/utils/Looper.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6LooperE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6LooperD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6LooperD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "referenced_type" : "_ZTIRN7android6RWLockE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLock9AutoRLockE",
+ "name" : "android::RWLock::AutoRLock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoRLockE",
+ "self_type" : "_ZTIN7android6RWLock9AutoRLockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "referenced_type" : "_ZTIRN7android6RWLockE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLock9AutoWLockE",
+ "name" : "android::RWLock::AutoWLock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6RWLock9AutoWLockE",
+ "self_type" : "_ZTIN7android6RWLock9AutoWLockE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mRWLock",
+ "referenced_type" : "_ZTI16pthread_rwlock_t"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6RWLockE",
+ "name" : "android::RWLock",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6RWLockE",
+ "self_type" : "_ZTIN7android6RWLockE",
+ "size" : 40,
+ "source_file" : "system/core/libutils/include/utils/RWLock.h"
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "is_virtual" : true,
+ "referenced_type" : "_ZTIN7android7RefBaseE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCanCallJava",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIKb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mThread",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLock",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIN7android5MutexE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mThreadExitedCondition",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIN7android9ConditionE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mStatus",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mExitPending",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIVb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mRunning",
+ "field_offset" : 200,
+ "referenced_type" : "_ZTIVb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mHoldSelf",
+ "field_offset" : 224,
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mTid",
+ "field_offset" : 256,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6ThreadE",
+ "name" : "android::Thread",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6ThreadE",
+ "self_type" : "_ZTIN7android6ThreadE",
+ "size" : 44,
+ "source_file" : "system/core/libutils/include/utils/Thread.h",
+ "vtable_components" :
+ [
+ {
+ "component_value" : 36,
+ "kind" : "vbase_offset"
+ },
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6ThreadE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6ThreadD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6ThreadD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android6Thread3runEPKcij"
+ },
+ {
+ "mangled_component_name" : "_ZN7android6Thread11requestExitEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android6Thread10readyToRunEv"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android6Thread10threadLoopEv"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -36,
+ "kind" : "vcall_offset"
+ },
+ {
+ "component_value" : -36,
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6ThreadE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android6ThreadD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZTv0_n12_N7android6ThreadD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::Vector<android::sysprop_change_callback_info>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_28sysprop_change_callback_infoEEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_28sysprop_change_callback_infoEED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_28sysprop_change_callback_infoEED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE12do_constructEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE10do_destroyEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE7do_copyEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE8do_splatEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE15do_move_forwardEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_28sysprop_change_callback_infoEE16do_move_backwardEPvPKvj"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::Vector<android::Looper::MessageEnvelope>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_6Looper15MessageEnvelopeEEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper15MessageEnvelopeEED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper15MessageEnvelopeEED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE12do_constructEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE10do_destroyEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE7do_copyEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE8do_splatEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE15do_move_forwardEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper15MessageEnvelopeEE16do_move_backwardEPvPKvj"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "name" : "android::Vector<android::Looper::Response>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_6Looper8ResponseEEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper8ResponseEED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_6Looper8ResponseEED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE12do_constructEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE10do_destroyEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE7do_copyEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE8do_splatEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE15do_move_forwardEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_6Looper8ResponseEE16do_move_backwardEPvPKvj"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "access" : "private",
+ "referenced_type" : "_ZTIN7android10VectorImplE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android6VectorINS_7String8EEE",
+ "name" : "android::Vector<android::String8>",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "self_type" : "_ZTIN7android6VectorINS_7String8EEE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/Vector.h",
+ "template_args" :
+ [
+ "_ZTIN7android7String8E"
+ ],
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android6VectorINS_7String8EEE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_7String8EED1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android6VectorINS_7String8EED0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE12do_constructEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE10do_destroyEPvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE7do_copyEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE8do_splatEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE15do_move_forwardEPvPKvj"
+ },
+ {
+ "mangled_component_name" : "_ZNK7android6VectorINS_7String8EE16do_move_backwardEPvPKvj"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEEE",
+ "name" : "android::traits<android::sysprop_change_callback_info>",
+ "referenced_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEEE",
+ "self_type" : "_ZTIN7android6traitsINS_28sysprop_change_callback_infoEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android28sysprop_change_callback_infoE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEEE",
+ "name" : "android::traits<android::Looper::MessageEnvelope>",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEEE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper15MessageEnvelopeEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper15MessageEnvelopeE"
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android6traitsINS_6Looper8ResponseEEE",
+ "name" : "android::traits<android::Looper::Response>",
+ "referenced_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEEE",
+ "self_type" : "_ZTIN7android6traitsINS_6Looper8ResponseEEE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/TypeHelpers.h",
+ "template_args" :
+ [
+ "_ZTIN7android6Looper8ResponseE"
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFileName",
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mBasePtr",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mBaseLength",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mDataOffset",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIx"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mDataPtr",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIPv"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mDataLength",
+ "field_offset" : 224,
+ "referenced_type" : "_ZTIj"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7FileMapE",
+ "name" : "android::FileMap",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTIN7android7FileMapE",
+ "size" : 32,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "what",
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7MessageE",
+ "name" : "android::Message",
+ "referenced_type" : "_ZTIN7android7MessageE",
+ "self_type" : "_ZTIN7android7MessageE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Looper.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTIN7android7PrinterE",
+ "name" : "android::Printer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7PrinterE",
+ "self_type" : "_ZTIN7android7PrinterE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android7PrinterE"
+ },
+ {
+ "is_pure" : true,
+ "mangled_component_name" : "_ZN7android7Printer9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7PrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7PrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android7RefBase12weakref_typeE",
+ "name" : "android::RefBase::weakref_type",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "self_type" : "_ZTIN7android7RefBase12weakref_typeE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mRefs",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIKPN7android7RefBase12weakref_implE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7RefBaseE",
+ "name" : "android::RefBase",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7RefBaseE",
+ "self_type" : "_ZTIN7android7RefBaseE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/RefBase.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android7RefBaseE"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7RefBaseD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android7RefBaseD0Ev"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase10onFirstRefEv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase15onLastStrongRefEPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase20onIncStrongAttemptedEjPKv"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7RefBase13onLastWeakRefEPKv"
+ }
+ ]
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mString",
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android7String8E",
+ "name" : "android::String8",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android7String8E",
+ "self_type" : "_ZTIN7android7String8E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "size",
+ "referenced_type" : "_ZTIKj"
+ },
+ {
+ "field_name" : "data",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIA1_Ds"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android8String1610StaticDataILj1EEE",
+ "name" : "android::String16::StaticData<1>",
+ "referenced_type" : "_ZTIN7android8String1610StaticDataILj1EEE",
+ "self_type" : "_ZTIN7android8String1610StaticDataILj1EEE",
+ "size" : 8,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mString",
+ "referenced_type" : "_ZTIPKDs"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android8String16E",
+ "name" : "android::String16",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTIN7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ },
+ {
+ "alignment" : 1,
+ "linker_set_key" : "_ZTIN7android9CallStack12StackDeleterE",
+ "name" : "android::CallStack::StackDeleter",
+ "referenced_type" : "_ZTIN7android9CallStack12StackDeleterE",
+ "self_type" : "_ZTIN7android9CallStack12StackDeleterE",
+ "size" : 1,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFrameLines",
+ "referenced_type" : "_ZTIN7android6VectorINS_7String8EEE"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9CallStackE",
+ "name" : "android::CallStack",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9CallStackE",
+ "self_type" : "_ZTIN7android9CallStackE",
+ "size" : 20,
+ "source_file" : "system/core/libutils/include/utils/CallStack.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mCond",
+ "referenced_type" : "_ZTI14pthread_cond_t"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9ConditionE",
+ "name" : "android::Condition",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9ConditionE",
+ "self_type" : "_ZTIN7android9ConditionE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/Condition.h"
+ },
+ {
+ "alignment" : 4,
+ "base_specifiers" :
+ [
+ {
+ "referenced_type" : "_ZTIN7android7PrinterE"
+ }
+ ],
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFd",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mIndent",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mPrefix",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mFormatString",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIA20_c"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9FdPrinterE",
+ "name" : "android::FdPrinter",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9FdPrinterE",
+ "self_type" : "_ZTIN7android9FdPrinterE",
+ "size" : 36,
+ "source_file" : "system/core/libutils/include/utils/Printer.h",
+ "vtable_components" :
+ [
+ {
+ "kind" : "offset_to_top"
+ },
+ {
+ "kind" : "rtti",
+ "mangled_component_name" : "_ZTIN7android9FdPrinterE"
+ },
+ {
+ "mangled_component_name" : "_ZN7android9FdPrinter9printLineEPKc"
+ },
+ {
+ "mangled_component_name" : "_ZN7android7Printer15printFormatLineEPKcz"
+ },
+ {
+ "kind" : "complete_dtor_pointer",
+ "mangled_component_name" : "_ZN7android9FdPrinterD1Ev"
+ },
+ {
+ "kind" : "deleting_dtor_pointer",
+ "mangled_component_name" : "_ZN7android9FdPrinterD0Ev"
+ }
+ ]
+ },
+ {
+ "alignment" : 8,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mName",
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mClock",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIi"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mStartTime",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIx"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9StopWatchE",
+ "name" : "android::StopWatch",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9StopWatchE",
+ "self_type" : "_ZTIN7android9StopWatchE",
+ "size" : 16,
+ "source_file" : "system/core/libutils/include/utils/StopWatch.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "access" : "private",
+ "field_name" : "mFilename",
+ "referenced_type" : "_ZTIN7android7String8E"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mFileMap",
+ "field_offset" : 32,
+ "referenced_type" : "_ZTIPN7android7FileMapE"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mBuffer",
+ "field_offset" : 64,
+ "referenced_type" : "_ZTIPc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mOwnBuffer",
+ "field_offset" : 96,
+ "referenced_type" : "_ZTIb"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLength",
+ "field_offset" : 128,
+ "referenced_type" : "_ZTIj"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mCurrent",
+ "field_offset" : 160,
+ "referenced_type" : "_ZTIPKc"
+ },
+ {
+ "access" : "private",
+ "field_name" : "mLineNumber",
+ "field_offset" : 192,
+ "referenced_type" : "_ZTIi"
+ }
+ ],
+ "linker_set_key" : "_ZTIN7android9TokenizerE",
+ "name" : "android::Tokenizer",
+ "record_kind" : "class",
+ "referenced_type" : "_ZTIN7android9TokenizerE",
+ "self_type" : "_ZTIN7android9TokenizerE",
+ "size" : 28,
+ "source_file" : "system/core/libutils/include/utils/Tokenizer.h"
+ },
+ {
+ "alignment" : 4,
+ "fields" :
+ [
+ {
+ "field_name" : "buf",
+ "referenced_type" : "_ZTIA5121_h"
+ },
+ {
+ "field_name" : "entry",
+ "referenced_type" : "_ZTI12logger_entry"
+ }
+ ],
+ "is_anonymous" : true,
+ "linker_set_key" : "_ZTIN7log_msgUt_E",
+ "name" : "log_msg::(anonymous)",
+ "record_kind" : "union",
+ "referenced_type" : "_ZTIN7log_msgUt_E",
+ "self_type" : "_ZTIN7log_msgUt_E",
+ "size" : 5124,
+ "source_file" : "system/logging/liblog/include_vndk/log/log_read.h"
+ }
+ ],
+ "rvalue_reference_types" :
+ [
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android2spINS_12NativeHandleEEE",
+ "name" : "android::sp<android::NativeHandle> &&",
+ "referenced_type" : "_ZTIN7android2spINS_12NativeHandleEEE",
+ "self_type" : "_ZTION7android2spINS_12NativeHandleEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android2spINS_14MessageHandlerEEE",
+ "name" : "android::sp<android::MessageHandler> &&",
+ "referenced_type" : "_ZTIN7android2spINS_14MessageHandlerEEE",
+ "self_type" : "_ZTION7android2spINS_14MessageHandlerEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android2spINS_20SimpleLooperCallbackEEE",
+ "name" : "android::sp<android::SimpleLooperCallback> &&",
+ "referenced_type" : "_ZTIN7android2spINS_20SimpleLooperCallbackEEE",
+ "self_type" : "_ZTION7android2spINS_20SimpleLooperCallbackEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android2spINS_6LooperEEE",
+ "name" : "android::sp<android::Looper> &&",
+ "referenced_type" : "_ZTIN7android2spINS_6LooperEEE",
+ "self_type" : "_ZTION7android2spINS_6LooperEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android2spINS_6ThreadEEE",
+ "name" : "android::sp<android::Thread> &&",
+ "referenced_type" : "_ZTIN7android2spINS_6ThreadEEE",
+ "self_type" : "_ZTION7android2spINS_6ThreadEEE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/StrongPointer.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "name" : "android::base::unique_fd_impl<android::base::DefaultCloser> &&",
+ "referenced_type" : "_ZTIN7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "self_type" : "_ZTION7android4base14unique_fd_implINS0_13DefaultCloserEEE",
+ "size" : 4,
+ "source_file" : "system/libbase/include/android-base/unique_fd.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android7FileMapE",
+ "name" : "android::FileMap &&",
+ "referenced_type" : "_ZTIN7android7FileMapE",
+ "self_type" : "_ZTION7android7FileMapE",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/FileMap.h"
+ },
+ {
+ "alignment" : 4,
+ "linker_set_key" : "_ZTION7android8String16E",
+ "name" : "android::String16 &&",
+ "referenced_type" : "_ZTIN7android8String16E",
+ "self_type" : "_ZTION7android8String16E",
+ "size" : 4,
+ "source_file" : "system/core/libutils/include/utils/String16.h"
+ }
+ ]
+}
diff --git a/libutils/include/utils/LruCache.h b/libutils/include/utils/LruCache.h
index b4243a3..70901b6 100644
--- a/libutils/include/utils/LruCache.h
+++ b/libutils/include/utils/LruCache.h
@@ -161,12 +161,12 @@
// Implementation is here, because it's fully templated
template <typename TKey, typename TValue>
LruCache<TKey, TValue>::LruCache(uint32_t maxCapacity)
- : mSet(new LruCacheSet())
- , mListener(nullptr)
- , mOldest(nullptr)
- , mYoungest(nullptr)
- , mMaxCapacity(maxCapacity)
- , mNullValue(0) {
+ : mSet(new LruCacheSet()),
+ mListener(nullptr),
+ mOldest(nullptr),
+ mYoungest(nullptr),
+ mMaxCapacity(maxCapacity),
+ mNullValue{} {
mSet->max_load_factor(1.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/mkbootfs/mkbootfs.c b/mkbootfs/mkbootfs.c
index 05d1940..d3922bf 100644
--- a/mkbootfs/mkbootfs.c
+++ b/mkbootfs/mkbootfs.c
@@ -1,40 +1,32 @@
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <ctype.h>
-
-#include <sys/types.h>
#include <sys/stat.h>
-#include <dirent.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <unistd.h>
-#include <stdarg.h>
-#include <fcntl.h>
+#include <linux/kdev_t.h>
#include <private/android_filesystem_config.h>
#include <private/fs_config.h>
/* NOTES
**
-** - see buffer-format.txt from the linux kernel docs for
-** an explanation of this file format
+** - see https://www.kernel.org/doc/Documentation/early-userspace/buffer-format.txt
+** for an explanation of this file format
** - dotfiles are ignored
** - directories named 'root' are ignored
-** - device notes, pipes, etc are not supported (error)
*/
-static void die(const char* why, ...) {
- va_list ap;
-
- va_start(ap, why);
- fprintf(stderr,"error: ");
- vfprintf(stderr, why, ap);
- fprintf(stderr,"\n");
- va_end(ap);
- exit(1);
-}
-
struct fs_config_entry {
char* name;
int uid, gid, mode;
@@ -43,17 +35,8 @@
static struct fs_config_entry* canned_config = NULL;
static const char* target_out_path = NULL;
-/* Each line in the canned file should be a path plus three ints (uid,
- * gid, mode). */
-#ifdef PATH_MAX
-#define CANNED_LINE_LENGTH (PATH_MAX+100)
-#else
-#define CANNED_LINE_LENGTH (1024)
-#endif
-
#define TRAILER "TRAILER!!!"
-static int verbose = 0;
static int total_size = 0;
static void fix_stat(const char *path, struct stat *s)
@@ -86,6 +69,10 @@
fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
s->st_mode = (typeof(s->st_mode)) st_mode;
}
+
+ if (S_ISREG(s->st_mode) || S_ISDIR(s->st_mode) || S_ISLNK(s->st_mode)) {
+ s->st_rdev = 0;
+ }
}
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
@@ -115,8 +102,8 @@
datasize,
0, // volmajor
0, // volminor
- 0, // devmajor
- 0, // devminor,
+ major(s->st_rdev),
+ minor(s->st_rdev),
olen + 1,
0,
out,
@@ -125,7 +112,7 @@
total_size += 6 + 8*13 + olen + 1;
- if(strlen(out) != (unsigned int)olen) die("ACK!");
+ if(strlen(out) != (unsigned int)olen) errx(1, "ACK!");
while(total_size & 3) {
total_size++;
@@ -159,23 +146,16 @@
static void _archive_dir(char *in, char *out, int ilen, int olen)
{
int i, t;
- DIR *d;
struct dirent *de;
- if(verbose) {
- fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n",
- in, out, ilen, olen);
- }
-
- d = opendir(in);
- if(d == 0) die("cannot open directory '%s'", in);
+ DIR* d = opendir(in);
+ if (d == NULL) err(1, "cannot open directory '%s'", in);
int size = 32;
int entries = 0;
char** names = malloc(size * sizeof(char*));
if (names == NULL) {
- fprintf(stderr, "failed to allocate dir names array (size %d)\n", size);
- exit(1);
+ errx(1, "failed to allocate dir names array (size %d)", size);
}
while((de = readdir(d)) != 0){
@@ -189,16 +169,12 @@
size *= 2;
names = realloc(names, size * sizeof(char*));
if (names == NULL) {
- fprintf(stderr, "failed to reallocate dir names array (size %d)\n",
- size);
- exit(1);
+ errx(1, "failed to reallocate dir names array (size %d)", size);
}
}
names[entries] = strdup(de->d_name);
if (names[entries] == NULL) {
- fprintf(stderr, "failed to strdup name \"%s\"\n",
- de->d_name);
- exit(1);
+ errx(1, "failed to strdup name \"%s\"", de->d_name);
}
++entries;
}
@@ -232,26 +208,17 @@
static void _archive(char *in, char *out, int ilen, int olen)
{
struct stat s;
-
- if(verbose) {
- fprintf(stderr,"_archive('%s','%s',%d,%d)\n",
- in, out, ilen, olen);
- }
-
- if(lstat(in, &s)) die("could not stat '%s'\n", in);
+ if(lstat(in, &s)) err(1, "could not stat '%s'", in);
if(S_ISREG(s.st_mode)){
- char *tmp;
- int fd;
+ int fd = open(in, O_RDONLY);
+ if(fd < 0) err(1, "cannot open '%s' for read", in);
- fd = open(in, O_RDONLY);
- if(fd < 0) die("cannot open '%s' for read", in);
-
- tmp = (char*) malloc(s.st_size);
- if(tmp == 0) die("cannot allocate %d bytes", s.st_size);
+ char* tmp = (char*) malloc(s.st_size);
+ if(tmp == 0) errx(1, "cannot allocate %zd bytes", s.st_size);
if(read(fd, tmp, s.st_size) != s.st_size) {
- die("cannot read %d bytes", s.st_size);
+ err(1, "cannot read %zd bytes", s.st_size);
}
_eject(&s, out, olen, tmp, s.st_size);
@@ -265,10 +232,13 @@
char buf[1024];
int size;
size = readlink(in, buf, 1024);
- if(size < 0) die("cannot read symlink '%s'", in);
+ if(size < 0) err(1, "cannot read symlink '%s'", in);
_eject(&s, out, olen, buf, size);
+ } else if(S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) ||
+ S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode)) {
+ _eject(&s, out, olen, NULL, 0);
} else {
- die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
+ errx(1, "Unknown '%s' (mode %d)?", in, s.st_mode);
}
}
@@ -290,17 +260,18 @@
canned_config =
(struct fs_config_entry*)malloc(allocated * sizeof(struct fs_config_entry));
- char line[CANNED_LINE_LENGTH];
- FILE* f = fopen(filename, "r");
- if (f == NULL) die("failed to open canned file '%s'", filename);
+ FILE* fp = fopen(filename, "r");
+ if (fp == NULL) err(1, "failed to open canned file '%s'", filename);
- while (fgets(line, CANNED_LINE_LENGTH, f) != NULL) {
+ char* line = NULL;
+ size_t allocated_len;
+ while (getline(&line, &allocated_len, fp) != -1) {
if (!line[0]) break;
if (used >= allocated) {
allocated *= 2;
canned_config = (struct fs_config_entry*)realloc(
canned_config, allocated * sizeof(struct fs_config_entry));
- if (canned_config == NULL) die("failed to reallocate memory");
+ if (canned_config == NULL) errx(1, "failed to reallocate memory");
}
struct fs_config_entry* cc = canned_config + used;
@@ -320,41 +291,166 @@
++allocated;
canned_config = (struct fs_config_entry*)realloc(
canned_config, allocated * sizeof(struct fs_config_entry));
- if (canned_config == NULL) die("failed to reallocate memory");
+ if (canned_config == NULL) errx(1, "failed to reallocate memory");
}
canned_config[used].name = NULL;
- fclose(f);
+ free(line);
+ fclose(fp);
}
+static void devnodes_desc_error(const char* filename, unsigned long line_num,
+ const char* msg)
+{
+ errx(1, "failed to read nodes desc file '%s' line %lu: %s", filename, line_num, msg);
+}
+
+static int append_devnodes_desc_dir(char* path, char* args)
+{
+ struct stat s;
+
+ if (sscanf(args, "%o %d %d", &s.st_mode, &s.st_uid, &s.st_gid) != 3) return -1;
+
+ s.st_mode |= S_IFDIR;
+
+ _eject(&s, path, strlen(path), NULL, 0);
+
+ return 0;
+}
+
+static int append_devnodes_desc_nod(char* path, char* args)
+{
+ int minor, major;
+ struct stat s;
+ char dev;
+
+ if (sscanf(args, "%o %d %d %c %d %d", &s.st_mode, &s.st_uid, &s.st_gid,
+ &dev, &major, &minor) != 6) return -1;
+
+ s.st_rdev = MKDEV(major, minor);
+ switch (dev) {
+ case 'b':
+ s.st_mode |= S_IFBLK;
+ break;
+ case 'c':
+ s.st_mode |= S_IFCHR;
+ break;
+ default:
+ return -1;
+ }
+
+ _eject(&s, path, strlen(path), NULL, 0);
+
+ return 0;
+}
+
+static void append_devnodes_desc(const char* filename)
+{
+ FILE* fp = fopen(filename, "re");
+ if (!fp) err(1, "failed to open nodes description file '%s'", filename);
+
+ unsigned long line_num = 0;
+
+ char* line = NULL;
+ size_t allocated_len;
+ while (getline(&line, &allocated_len, fp) != -1) {
+ char *type, *path, *args;
+
+ line_num++;
+
+ if (*line == '#') continue;
+
+ if (!(type = strtok(line, " \t"))) {
+ devnodes_desc_error(filename, line_num, "a type is missing");
+ }
+
+ if (*type == '\n') continue;
+
+ if (!(path = strtok(NULL, " \t"))) {
+ devnodes_desc_error(filename, line_num, "a path is missing");
+ }
+
+ if (!(args = strtok(NULL, "\n"))) {
+ devnodes_desc_error(filename, line_num, "args are missing");
+ }
+
+ if (!strcmp(type, "dir")) {
+ if (append_devnodes_desc_dir(path, args)) {
+ devnodes_desc_error(filename, line_num, "bad arguments for dir");
+ }
+ } else if (!strcmp(type, "nod")) {
+ if (append_devnodes_desc_nod(path, args)) {
+ devnodes_desc_error(filename, line_num, "bad arguments for nod");
+ }
+ } else {
+ devnodes_desc_error(filename, line_num, "type unknown");
+ }
+ }
+
+ free(line);
+ fclose(fp);
+}
+
+static const struct option long_options[] = {
+ { "dirname", required_argument, NULL, 'd' },
+ { "file", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "nodes", required_argument, NULL, 'n' },
+ { NULL, 0, NULL, 0 },
+};
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "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"
+ "\t-h, --help: Print this help\n"
+ "\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"
+ "\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"
+ );
+}
int main(int argc, char *argv[])
{
- if (argc == 1) {
- fprintf(stderr,
- "usage: %s [-d TARGET_OUTPUT_PATH] [-f CANNED_CONFIGURATION_PATH] DIRECTORIES...\n",
- argv[0]);
- exit(1);
+ int opt, unused;
+
+ while ((opt = getopt_long(argc, argv, "hd:f:n:", long_options, &unused)) != -1) {
+ switch (opt) {
+ case 'd':
+ target_out_path = argv[optind - 1];
+ break;
+ case 'f':
+ read_canned_config(argv[optind - 1]);
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'n':
+ append_devnodes_desc(argv[optind - 1]);
+ break;
+ default:
+ usage();
+ errx(1, "Unknown option %s", argv[optind - 1]);
+ }
}
- argc--;
- argv++;
+ int num_dirs = argc - optind;
+ argv += optind;
- if (argc > 1 && strcmp(argv[0], "-d") == 0) {
- target_out_path = argv[1];
- argc -= 2;
- argv += 2;
+ if (num_dirs <= 0) {
+ usage();
+ errx(1, "no directories to process?!");
}
- if (argc > 1 && strcmp(argv[0], "-f") == 0) {
- read_canned_config(argv[1]);
- argc -= 2;
- argv += 2;
- }
-
- if(argc == 0) die("no directories to process?!");
-
- while(argc-- > 0){
+ while(num_dirs-- > 0){
char *x = strchr(*argv, '=');
if(x != 0) {
*x++ = 0;
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index fe23b62..3362872 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -213,4 +213,17 @@
$(hide) $(foreach lib,$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES), \
echo $(lib) >> $@;)
+#######################################
+# ramdisk_node_list
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ramdisk_node_list
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)
+
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+include $(BUILD_PREBUILT)
+
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index 967205f..cacc47c 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -5,6 +5,7 @@
libbinder_ndk.so
libc.so
libcamera2ndk.so
+libclang_rt.hwasan-aarch64-android.so 64 nopreload
libdl.so
libEGL.so
libGLESv1_CM.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1131f3f..a8b78d5 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -47,6 +47,9 @@
# Allow up to 32K FDs per process
setrlimit nofile 32768 32768
+ # set RLIMIT_MEMLOCK to 64KB
+ setrlimit memlock 65536 65536
+
# Set up linker config subdirectories based on mount namespaces
mkdir /linkerconfig/bootstrap 0755
mkdir /linkerconfig/default 0755
@@ -55,10 +58,11 @@
# Read more in b/136247322
write /sys/module/dm_verity/parameters/prefetch_cluster 0
- # Generate ld.config.txt for early executed processes
- exec -- /system/bin/bootstrap/linkerconfig --target /linkerconfig/bootstrap
+ # Generate empty ld.config.txt for early executed processes which rely on
+ # /system/lib libraries.
+ write /linkerconfig/bootstrap/ld.config.txt \#
+ write /linkerconfig/default/ld.config.txt \#
chmod 644 /linkerconfig/bootstrap/ld.config.txt
- copy /linkerconfig/bootstrap/ld.config.txt /linkerconfig/default/ld.config.txt
chmod 644 /linkerconfig/default/ld.config.txt
# Mount bootstrap linker configuration as current
@@ -217,26 +221,6 @@
write /dev/stune/nnapi-hal/schedtune.boost 1
write /dev/stune/nnapi-hal/schedtune.prefer_idle 1
- # Create blkio group and apply initial settings.
- # This feature needs kernel to support it, and the
- # device's init.rc must actually set the correct values.
- mkdir /dev/blkio/background
- chown system system /dev/blkio
- chown system system /dev/blkio/background
- chown system system /dev/blkio/tasks
- chown system system /dev/blkio/background/tasks
- chown system system /dev/blkio/cgroup.procs
- chown system system /dev/blkio/background/cgroup.procs
- chmod 0664 /dev/blkio/tasks
- chmod 0664 /dev/blkio/background/tasks
- chmod 0664 /dev/blkio/cgroup.procs
- chmod 0664 /dev/blkio/background/cgroup.procs
- write /dev/blkio/blkio.weight 1000
- write /dev/blkio/background/blkio.weight 200
- write /dev/blkio/background/blkio.bfq.weight 10
- write /dev/blkio/blkio.group_idle 0
- write /dev/blkio/background/blkio.group_idle 0
-
restorecon_recursive /mnt
mount configfs none /config nodev noexec nosuid
@@ -311,7 +295,7 @@
write /proc/sys/kernel/randomize_va_space 2
write /proc/sys/vm/mmap_min_addr 32768
write /proc/sys/net/ipv4/ping_group_range "0 2147483647"
- write /proc/sys/net/unix/max_dgram_qlen 600
+ write /proc/sys/net/unix/max_dgram_qlen 2400
# Assign reasonable ceiling values for socket rcv/snd buffers.
# These should almost always be overridden by the target per the
@@ -489,19 +473,30 @@
service boringssl_self_test32 /system/bin/boringssl_self_test32
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test32 doesn't require any capabilities
+ capabilities
+ user nobody
service boringssl_self_test64 /system/bin/boringssl_self_test64
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test64 doesn't require any capabilities
+ capabilities
+ user nobody
service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test_apex32 doesn't require any capabilities
+ capabilities
+ user nobody
service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
-
+ # Explicitly specify that boringssl_self_test_apex64 doesn't require any capabilities
+ capabilities
+ user nobody
# Healthd can trigger a full boot from charger mode by signaling this
# property when the power button is held.
@@ -631,7 +626,7 @@
chmod 0755 /sys/kernel/tracing
chmod 0755 /sys/kernel/debug/tracing
- # HALs required before storage encryption can get unlocked (FBE/FDE)
+ # HALs required before storage encryption can get unlocked (FBE)
class_start early_hal
# Load trusted keys from dm-verity protected partitions
@@ -734,9 +729,8 @@
# /data/apex is now available. Start apexd to scan and activate APEXes.
#
- # To handle userspace reboots as well as devices that use FDE, make sure
- # that apexd is started cleanly here (set apexd.status="") and that it is
- # restarted if it's already running.
+ # To handle userspace reboots, make sure that apexd is started cleanly here
+ # (set apexd.status="") and that it is restarted if it's already running.
#
# /data/apex uses encryption=None because direct I/O support is needed on
# APEX files, but some devices don't support direct I/O on encrypted files.
@@ -838,7 +832,7 @@
# Delete any stale files owned by the old virtualizationservice uid (b/230056726).
chmod 0770 /data/misc/virtualizationservice
exec - virtualizationservice system -- /bin/rm -rf /data/misc/virtualizationservice
- mkdir /data/misc/virtualizationservice 0770 system system
+ mkdir /data/misc/virtualizationservice 0771 system system
# /data/preloads uses encryption=None because it only contains preloaded
# files that are public information, similar to the system image.
@@ -914,6 +908,10 @@
mkdir /data/system/dropbox 0700 system system
mkdir /data/system/heapdump 0700 system system
mkdir /data/system/users 0775 system system
+ # Mkdir and set SELinux security contexts for shutdown-checkpoints.
+ # TODO(b/270286197): remove these after couple releases.
+ mkdir /data/system/shutdown-checkpoints 0700 system system
+ restorecon_recursive /data/system/shutdown-checkpoints
# Create the parent directories of the user CE and DE storage directories.
# These parent directories must use encryption=None, since each of their
@@ -921,31 +919,42 @@
# encryption policies apply recursively. These directories should never
# contain any subdirectories other than the per-user ones. /data/media/obb
# is an exception that exists for legacy reasons.
- mkdir /data/media 0770 media_rw media_rw encryption=None
- mkdir /data/misc_ce 01771 system misc encryption=None
- mkdir /data/misc_de 01771 system misc encryption=None
- mkdir /data/system_ce 0770 system system encryption=None
- mkdir /data/system_de 0770 system system encryption=None
- mkdir /data/user 0711 system system encryption=None
- mkdir /data/user_de 0711 system system encryption=None
- mkdir /data/vendor_ce 0771 root root encryption=None
- mkdir /data/vendor_de 0771 root root encryption=None
+ #
+ # Don't use any write mode bits (0222) for any of these directories, since
+ # the only process that should write to them directly is vold (since it
+ # needs to set up file-based encryption on the subdirectories), which runs
+ # as root with CAP_DAC_OVERRIDE. This is also fully enforced via the
+ # SELinux policy. But we also set the DAC file modes accordingly, to try to
+ # minimize differences in behavior if SELinux is set to permissive mode.
+ mkdir /data/media 0550 media_rw media_rw encryption=None
+ mkdir /data/misc_ce 0551 system misc encryption=None
+ mkdir /data/misc_de 0551 system misc encryption=None
+ mkdir /data/system_ce 0550 system system encryption=None
+ mkdir /data/system_de 0550 system system encryption=None
+ mkdir /data/user 0511 system system encryption=None
+ mkdir /data/user_de 0511 system system encryption=None
+ mkdir /data/vendor_ce 0551 root root encryption=None
+ mkdir /data/vendor_de 0551 root root encryption=None
# Set the casefold flag on /data/media. For upgrades, a restorecon can be
# needed first to relabel the directory from media_rw_data_file.
restorecon /data/media
exec - media_rw media_rw -- /system/bin/chattr +F /data/media
- # A tmpfs directory, which will contain all apps CE DE data directory that
- # bind mount from the original source.
+ # A tmpfs directory, which will contain all apps and sdk sandbox CE and DE
+ # data directory that bind mount from the original source.
mount tmpfs tmpfs /data_mirror nodev noexec nosuid mode=0700,uid=0,gid=1000
restorecon /data_mirror
mkdir /data_mirror/data_ce 0700 root root
mkdir /data_mirror/data_de 0700 root root
+ mkdir /data_mirror/misc_ce 0700 root root
+ mkdir /data_mirror/misc_de 0700 root root
# Create CE and DE data directory for default volume
mkdir /data_mirror/data_ce/null 0700 root root
mkdir /data_mirror/data_de/null 0700 root root
+ mkdir /data_mirror/misc_ce/null 0700 root root
+ mkdir /data_mirror/misc_de/null 0700 root root
# Bind mount CE and DE data directory to mirror's default volume directory.
# Note that because the /data mount has the "shared" propagation type, the
@@ -953,6 +962,8 @@
# propagate to /data_mirror/data_ce/null/0 as well.
mount none /data/user /data_mirror/data_ce/null bind rec
mount none /data/user_de /data_mirror/data_de/null bind rec
+ mount none /data/misc_ce /data_mirror/misc_ce/null bind rec
+ mount none /data/misc_de /data_mirror/misc_de/null bind rec
# Create mirror directory for jit profiles
mkdir /data_mirror/cur_profiles 0700 root root
@@ -976,6 +987,7 @@
# Create directories for statsd
mkdir /data/misc/stats-active-metric/ 0770 statsd system
mkdir /data/misc/stats-data/ 0770 statsd system
+ mkdir /data/misc/stats-data/restricted-data 0770 statsd system
mkdir /data/misc/stats-metadata/ 0770 statsd system
mkdir /data/misc/stats-service/ 0770 statsd system
mkdir /data/misc/train-info/ 0770 statsd system
@@ -999,6 +1011,11 @@
exec_start derive_classpath
load_exports /data/system/environ/classpath
+ # Start ART's oneshot boot service to propagate boot experiment flags to
+ # dalvik.vm.*. This needs to be done before odsign since odrefresh uses and
+ # validates those properties against the signed cache-info.xml.
+ exec_start art_boot
+
# Start the on-device signing daemon, and wait for it to finish, to ensure
# ART artifacts are generated if needed.
# Must start after 'derive_classpath' to have *CLASSPATH variables set.
@@ -1112,7 +1129,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)
@@ -1258,6 +1275,7 @@
class core
critical
seclabel u:r:ueventd:s0
+ user root
shutdown critical
service console /system/bin/sh
@@ -1268,13 +1286,16 @@
group shell log readproc
seclabel u:r:shell:s0
setenv HOSTNAME console
+ shutdown critical
on property:ro.debuggable=1
- # Give writes to anyone for the trace folder on debug builds.
+ # Give writes to the same group for the trace folder on debug builds,
+ # it's further protected by selinux policy.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
- # Give reads to anyone for the window trace folder on debug builds.
- chmod 0775 /data/misc/wmtrace
+ # Give writes and reads to anyone for the window trace folder on debug builds,
+ # it's further protected by selinux policy.
+ chmod 0777 /data/misc/wmtrace
# Give reads to anyone for the accessibility trace folder on debug builds.
chmod 0775 /data/misc/a11ytrace
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index 0730cce..dde784e 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -18,6 +18,7 @@
disabled
updatable
seclabel u:r:adbd:s0
+ user root
on property:vendor.sys.usb.adb.disabled=*
setprop sys.usb.adb.disabled ${vendor.sys.usb.adb.disabled}
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 63b09c0..2f0ec8a 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -7,6 +7,9 @@
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
+ # NOTE: If the wakelock name here is changed, then also
+ # update it in SystemSuspend.cpp
+ onrestart write /sys/power/wake_lock zygote_kwl
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index b6ca5c0..74a64c8 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -7,6 +7,9 @@
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
+ # NOTE: If the wakelock name here is changed, then also
+ # update it in SystemSuspend.cpp
+ onrestart write /sys/power/wake_lock zygote_kwl
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
diff --git a/rootdir/ramdisk_node_list b/rootdir/ramdisk_node_list
new file mode 100644
index 0000000..4f45faa
--- /dev/null
+++ b/rootdir/ramdisk_node_list
@@ -0,0 +1,4 @@
+dir dev 0755 0 0
+nod dev/null 0600 0 0 c 1 3
+nod dev/console 0600 0 0 c 5 1
+nod dev/urandom 0600 0 0 c 1 9
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 4ec59af..0b7ffb8 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -69,8 +69,8 @@
# CDMA radio interface MUX
/dev/ppp 0660 radio vpn
-/dev/kvm 0600 system system
-/dev/vhost-vsock 0600 system system
+/dev/kvm 0666 root root
+/dev/vhost-vsock 0666 root root
# sysfs properties
/sys/devices/platform/trusty.* trusty_version 0440 root log
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index ca522b7..9a733bb 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -18,8 +18,11 @@
in Marshmallow we changed direction and started the move to toybox.
Not everything is provided by toybox, though. For the bzip2 command-line tools
-we use the ones that are part of the bzip2 distribution. The awk added in
-Android P is Brian Kernighan's "one true" awk.
+we use the ones that are part of the bzip2 distribution.
+The awk added in Android P is the
+["one true" awk](https://github.com/onetrueawk/awk).
+The bc added in Android Q is
+[Gavin Howard's bc](https://github.com/gavinhoward/bc).
The lists below show what tools were provided and where they came from in
each release starting with Gingerbread. This doesn't tell the full story,
@@ -34,6 +37,40 @@
full list for a release by running `toybox` directly.
+## Android 14 ("U")
+
+BSD: fsck\_msdos newfs\_msdos
+
+bzip2: bzcat bzip2 bunzip2
+
+gavinhoward/bc: bc
+
+one-true-awk: awk
+
+toolbox: getevent getprop setprop start stop
+
+toybox ([0.8.9](http://landley.net/toybox/#10-01-2023)-ish):
+[ acpi base64 basename blkdiscard blkid blockdev **brctl** cal cat chattr
+chcon chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut
+date dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
+expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
+fsync getconf getenforce getfattr getopt grep groups gunzip gzip head
+help hostname hwclock i2cdetect i2cdump i2cget i2cset iconv id ifconfig
+inotifyd insmod install ionice iorenice iotop kill killall ln load\_policy
+log **logger** logname losetup ls lsattr lsmod lsof lspci lsusb makedevs
+md5sum microcom mkdir mkfifo mknod mkswap mktemp modinfo modprobe
+more mount mountpoint mv nbd-client nc netcat netstat nice nl nohup
+nproc nsenter od partprobe paste patch pgrep pidof ping ping6 pivot\_root
+pkill pmap printenv printf prlimit ps pwd pwdx readelf readlink realpath
+renice restorecon rev rfkill rm rmdir rmmod rtcwake runcon sed sendevent
+seq setenforce setfattr setsid sha1sum sha224sum sha256sum sha384sum
+sha512sum sleep sort split stat strings stty swapoff swapon sync sysctl
+tac tail tar taskset tee test time timeout top touch tr traceroute
+traceroute6 true truncate tty tunctl uclampset ulimit umount uname
+uniq unix2dos unlink unshare uptime usleep uudecode uuencode uuidgen
+vconfig vi vmstat watch wc which whoami xargs xxd yes zcat
+
+
## Android 13 ("T")
BSD: fsck\_msdos newfs\_msdos
@@ -46,7 +83,8 @@
toolbox: getevent getprop setprop start stop
-toybox (0.8.6-ish): [ acpi base64 basename blkdiscard blkid blockdev cal cat chattr chcon
+toybox ([0.8.6](http://landley.net/toybox/#30-11-2021)-ish):
+[ acpi base64 basename blkdiscard blkid blockdev cal cat chattr chcon
chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut date
dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
@@ -79,7 +117,8 @@
toolbox: getevent getprop setprop start stop
-toybox (0.8.4-ish): **[** acpi base64 basename **blkdiscard** blkid blockdev cal cat chattr chcon
+toybox ([0.8.4](http://landley.net/toybox/#24-10-2020)-ish):
+**[** acpi base64 basename **blkdiscard** blkid blockdev cal cat chattr chcon
chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut date
dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
@@ -112,7 +151,8 @@
toolbox: getevent getprop setprop start stop
-toybox (0.8.3-ish): acpi base64 basename blkid blockdev cal cat chattr chcon chgrp chmod
+toybox ([0.8.3](http://landley.net/toybox/#11-05-2020)-ish):
+acpi base64 basename blkid blockdev cal cat chattr chcon chgrp chmod
chown chroot chrt cksum clear cmp comm cp cpio cut date dd **devmem**
df diff dirname dmesg dos2unix du echo egrep env expand expr fallocate
false fgrep file find flock fmt free freeramdisk fsfreeze **fsync** getconf
@@ -143,7 +183,8 @@
toolbox: getevent getprop
-toybox (0.8.0-ish): acpi base64 basename **bc** **blkid** blockdev cal cat **chattr** chcon chgrp
+toybox ([0.8.0](http://landley.net/toybox/#08-02-2019)-ish):
+acpi base64 basename **bc** **blkid** blockdev cal cat **chattr** chcon chgrp
chmod chown chroot chrt cksum clear cmp comm cp cpio cut date dd df
diff dirname dmesg dos2unix du echo **egrep** env expand expr fallocate
false **fgrep** file find flock fmt free **freeramdisk** **fsfreeze** **getconf**
@@ -174,7 +215,8 @@
toolbox: getevent getprop newfs\_msdos
-toybox (0.7.6-ish): acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+toybox ([0.7.6](http://landley.net/toybox/#24-02-2018)-ish):
+acpi base64 basename blockdev cal cat chcon chgrp chmod chown
chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
dos2unix du echo env expand expr fallocate false file find flock **fmt** free
getenforce groups gunzip gzip head hostname hwclock id ifconfig inotifyd
@@ -198,7 +240,8 @@
toolbox: getevent newfs\_msdos
-toybox (0.7.3-ish): acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+toybox ([0.7.3](http://landley.net/toybox/#21-02-2017)-ish):
+acpi base64 basename blockdev cal cat chcon chgrp chmod chown
chroot chrt cksum clear cmp comm cp cpio cut date df **diff** dirname dmesg
dos2unix du echo env expand expr fallocate false **file** find flock free
getenforce getprop groups **gunzip** **gzip** head hostname hwclock id ifconfig
@@ -221,7 +264,8 @@
toolbox: getevent iftop ioctl log nandread newfs\_msdos ps prlimit
sendevent start stop top
-toybox (0.7.0-ish): acpi **base64** basename blockdev bzcat cal cat chcon chgrp chmod
+toybox ([0.7.0](http://landley.net/toybox/#02-02-2016)-ish):
+acpi **base64** basename blockdev bzcat cal cat chcon chgrp chmod
chown chroot cksum clear comm cmp cp cpio cut date **df** dirname dmesg
dos2unix **du** echo env expand expr fallocate false find **flock** free
getenforce getprop groups head hostname hwclock id ifconfig inotifyd
@@ -242,7 +286,8 @@
toolbox: df getevent iftop ioctl ionice log ls lsof mount nandread
newfs\_msdos ps prlimit renice sendevent start stop top uptime watchprops
-toybox (0.5.2-ish): acpi basename blockdev bzcat cal cat chcon chgrp chmod chown
+toybox ([0.5.2](http://landley.net/toybox/#25-02-2015)-ish):
+acpi basename blockdev bzcat cal cat chcon chgrp chmod chown
chroot cksum clear comm cmp cp cpio cut date dirname dmesg dos2unix echo
env expand expr fallocate false find free getenforce getprop groups
head hostname hwclock id ifconfig inotifyd insmod kill load\_policy ln
diff --git a/storaged/Android.bp b/storaged/Android.bp
index 7960af3..fe8c1f3 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -24,7 +24,7 @@
shared_libs: [
"android.hardware.health@1.0",
"android.hardware.health@2.0",
- "android.hardware.health-V1-ndk",
+ "android.hardware.health-V2-ndk",
"libbase",
"libbinder",
"libbinder_ndk",
@@ -136,3 +136,37 @@
],
path: "binder",
}
+
+cc_defaults {
+ name: "storaged_service_fuzzer_defaults",
+ defaults: [
+ "storaged_defaults",
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ ],
+ static_libs: [
+ "libstoraged",
+ ],
+ fuzz_config: {
+ cc: [
+ "dvander@google.com",
+ ],
+ triage_assignee: "waghpawan@google.com",
+ },
+}
+
+cc_fuzz {
+ name: "storaged_service_fuzzer",
+ defaults: [
+ "storaged_service_fuzzer_defaults",
+ ],
+ srcs: ["tests/fuzzers/storaged_service_fuzzer.cpp"],
+}
+
+cc_fuzz {
+ name: "storaged_private_service_fuzzer",
+ defaults: [
+ "storaged_service_fuzzer_defaults",
+ ],
+ srcs: ["tests/fuzzers/storaged_private_service_fuzzer.cpp"],
+}
diff --git a/storaged/include/storaged_service.h b/storaged/include/storaged_service.h
index 7ec6864..bf7af80 100644
--- a/storaged/include/storaged_service.h
+++ b/storaged/include/storaged_service.h
@@ -28,6 +28,7 @@
using namespace android::os;
using namespace android::os::storaged;
+namespace android {
class StoragedService : public BinderService<StoragedService>, public BnStoraged {
private:
void dumpUidRecordsDebug(int fd, const vector<struct uid_record>& entries);
@@ -53,4 +54,5 @@
sp<IStoragedPrivate> get_storaged_pri_service();
+} // namespace android
#endif /* _STORAGED_SERVICE_H_ */
\ No newline at end of file
diff --git a/storaged/storaged_diskstats.cpp b/storaged/storaged_diskstats.cpp
index 1eae5a1..c315409 100644
--- a/storaged/storaged_diskstats.cpp
+++ b/storaged/storaged_diskstats.cpp
@@ -312,7 +312,7 @@
{
struct disk_perf perf = get_disk_perf(&mAccumulate_pub);
log_debug_disk_perf(&perf, "regular");
- log_event_disk_stats(&mAccumulate, "regular");
+ log_event_disk_stats(&mAccumulate_pub, "regular");
// Reset global structures
memset(&mAccumulate_pub, 0, sizeof(struct disk_stats));
}
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index 45f1d4d..00d36d7 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -38,6 +38,7 @@
extern sp<storaged_t> storaged_sp;
+namespace android {
status_t StoragedService::start() {
return BinderService<StoragedService>::publish();
}
@@ -218,3 +219,4 @@
return interface_cast<IStoragedPrivate>(binder);
}
+} // namespace android
\ No newline at end of file
diff --git a/storaged/tests/fuzzers/storaged_private_service_fuzzer.cpp b/storaged/tests/fuzzers/storaged_private_service_fuzzer.cpp
new file mode 100644
index 0000000..82eb796
--- /dev/null
+++ b/storaged/tests/fuzzers/storaged_private_service_fuzzer.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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 <fuzzbinder/libbinder_driver.h>
+
+#include <storaged.h>
+#include <storaged_service.h>
+
+sp<storaged_t> storaged_sp;
+
+extern "C" int LLVMFuzzerInitialize(int /**argc*/, char /****argv*/) {
+ storaged_sp = new storaged_t();
+ storaged_sp->init();
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto storagedPrivateService = new StoragedPrivateService();
+ fuzzService(storagedPrivateService, FuzzedDataProvider(data, size));
+ return 0;
+}
\ No newline at end of file
diff --git a/storaged/tests/fuzzers/storaged_service_fuzzer.cpp b/storaged/tests/fuzzers/storaged_service_fuzzer.cpp
new file mode 100644
index 0000000..d11ecc3
--- /dev/null
+++ b/storaged/tests/fuzzers/storaged_service_fuzzer.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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 <fuzzbinder/libbinder_driver.h>
+
+#include <storaged.h>
+#include <storaged_service.h>
+
+sp<storaged_t> storaged_sp;
+
+extern "C" int LLVMFuzzerInitialize(int /**argc*/, char /****argv*/) {
+ storaged_sp = new storaged_t();
+ storaged_sp->init();
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto storagedService = new StoragedService();
+ fuzzService(storagedService, FuzzedDataProvider(data, size));
+ return 0;
+}
\ No newline at end of file
diff --git a/storaged/tests/storaged_test.cpp b/storaged/tests/storaged_test.cpp
index bb71bf3..9a281c2 100644
--- a/storaged/tests/storaged_test.cpp
+++ b/storaged/tests/storaged_test.cpp
@@ -284,6 +284,8 @@
dsm_detect.update_mean();
dsm_detect.update_std();
+ // FixLater: avoid floating point loop counters
+ // NOLINTNEXTLINE(clang-analyzer-security.FloatLoopCounter,cert-flp30-c)
for (double i = 0; i < 2 * dsm_detect.mSigma; i += 0.5) {
struct disk_perf test_perf;
struct disk_perf test_mean = dsm_detect.mMean;
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 711586a..17d4e31 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -23,8 +23,11 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
+#include <android-base/stringprintf.h>
#include <modprobe/modprobe.h>
+#include <sys/utsname.h>
+
namespace {
enum modprobe_mode {
@@ -37,9 +40,8 @@
void print_usage(void) {
LOG(INFO) << "Usage:";
LOG(INFO);
- // -d option is required on Android
- LOG(INFO) << " modprobe [options] -d DIR [--all=FILE|MODULE]...";
- LOG(INFO) << " modprobe [options] -d DIR MODULE [symbol=value]...";
+ LOG(INFO) << " modprobe [options] [-d DIR] [--all=FILE|MODULE]...";
+ LOG(INFO) << " modprobe [options] [-d DIR] MODULE [symbol=value]...";
LOG(INFO);
LOG(INFO) << "Options:";
LOG(INFO) << " --all=FILE: FILE to acquire module names from";
@@ -83,6 +85,26 @@
}
}
+// Find directories in format of "/lib/modules/x.y.z-*".
+static int KernelVersionNameFilter(const dirent* de) {
+ unsigned int major, minor;
+ static std::string kernel_version;
+ utsname uts;
+
+ if (kernel_version.empty()) {
+ if ((uname(&uts) != 0) || (sscanf(uts.release, "%u.%u", &major, &minor) != 2)) {
+ LOG(ERROR) << "Could not parse the kernel version from uname";
+ return 0;
+ }
+ kernel_version = android::base::StringPrintf("%u.%u", major, minor);
+ }
+
+ if (android::base::StartsWith(de->d_name, kernel_version)) {
+ return 1;
+ }
+ return 0;
+}
+
} // anonymous namespace
extern "C" int modprobe_main(int argc, char** argv) {
@@ -189,6 +211,25 @@
}
}
+ if (mod_dirs.empty()) {
+ static constexpr auto LIB_MODULES_PREFIX = "/lib/modules/";
+ dirent** kernel_dirs = NULL;
+
+ int n = scandir(LIB_MODULES_PREFIX, &kernel_dirs, KernelVersionNameFilter, NULL);
+ if (n == -1) {
+ PLOG(ERROR) << "Failed to scan dir " << LIB_MODULES_PREFIX;
+ return EXIT_FAILURE;
+ } else if (n > 0) {
+ while (n--) {
+ mod_dirs.emplace_back(LIB_MODULES_PREFIX + std::string(kernel_dirs[n]->d_name));
+ }
+ }
+ free(kernel_dirs);
+
+ // Allow modules to be directly inside /lib/modules
+ mod_dirs.emplace_back(LIB_MODULES_PREFIX);
+ }
+
LOG(DEBUG) << "mode is " << mode;
LOG(DEBUG) << "mod_dirs is: " << android::base::Join(mod_dirs, " ");
LOG(DEBUG) << "modules is: " << android::base::Join(modules, " ");
@@ -204,11 +245,6 @@
return EXIT_FAILURE;
}
}
- if (mod_dirs.empty()) {
- LOG(ERROR) << "No module configuration directories given.";
- print_usage();
- return EXIT_FAILURE;
- }
if (parameter_count && modules.size() > 1) {
LOG(ERROR) << "Only one module may be loaded when specifying module parameters.";
print_usage();
diff --git a/trusty/confirmationui/fuzz/Android.bp b/trusty/confirmationui/fuzz/Android.bp
index 4780943..96804bd 100644
--- a/trusty/confirmationui/fuzz/Android.bp
+++ b/trusty/confirmationui/fuzz/Android.bp
@@ -26,7 +26,8 @@
"-DTRUSTY_APP_FILENAME=\"confirmationui.syms.elf\"",
],
fuzz_config: {
- cc: ["trong@google.com"],
+ cc: ["mikemcternan@google.com"],
+ componentid: 1290237,
},
}
@@ -40,7 +41,8 @@
"libdmabufheap",
],
fuzz_config: {
- cc: ["trong@google.com"],
+ cc: ["mikemcternan@google.com"],
+ componentid: 1290237,
},
// The initial corpus for this fuzzer was derived by dumping messages from/to
diff --git a/trusty/gatekeeper/Android.bp b/trusty/gatekeeper/Android.bp
index 81f012f..0b43754 100644
--- a/trusty/gatekeeper/Android.bp
+++ b/trusty/gatekeeper/Android.bp
@@ -24,11 +24,10 @@
}
cc_binary {
- name: "android.hardware.gatekeeper@1.0-service.trusty",
- defaults: ["hidl_defaults"],
+ name: "android.hardware.gatekeeper-service.trusty",
vendor: true,
relative_install_path: "hw",
- init_rc: ["android.hardware.gatekeeper@1.0-service.trusty.rc"],
+ init_rc: ["android.hardware.gatekeeper-service.trusty.rc"],
srcs: [
"service.cpp",
@@ -42,16 +41,21 @@
"-Werror",
],
+ static_libs: [
+ "libgflags",
+ ],
+
shared_libs: [
- "android.hardware.gatekeeper@1.0",
+ "android.hardware.gatekeeper-V1-ndk",
"libbase",
- "libhidlbase",
+ "libbinder_ndk",
"libgatekeeper",
+ "libhardware",
"libutils",
"liblog",
"libcutils",
"libtrusty",
],
- vintf_fragments: ["android.hardware.gatekeeper@1.0-service.trusty.xml"],
+ vintf_fragments: ["android.hardware.gatekeeper-service.trusty.xml"],
}
diff --git a/trusty/gatekeeper/android.hardware.gatekeeper-service.trusty.rc b/trusty/gatekeeper/android.hardware.gatekeeper-service.trusty.rc
new file mode 100644
index 0000000..66ecbd1
--- /dev/null
+++ b/trusty/gatekeeper/android.hardware.gatekeeper-service.trusty.rc
@@ -0,0 +1,4 @@
+service vendor.gatekeeper_default /vendor/bin/hw/android.hardware.gatekeeper-service.trusty
+ class hal
+ user system
+ group system
diff --git a/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.xml b/trusty/gatekeeper/android.hardware.gatekeeper-service.trusty.xml
similarity index 60%
rename from trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.xml
rename to trusty/gatekeeper/android.hardware.gatekeeper-service.trusty.xml
index 19714a8..c35421e 100644
--- a/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.xml
+++ b/trusty/gatekeeper/android.hardware.gatekeeper-service.trusty.xml
@@ -1,10 +1,9 @@
<manifest version="1.0" type="device">
- <hal format="hidl">
+ <hal format="aidl">
<name>android.hardware.gatekeeper</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
+ <version>1</version>
<interface>
- <name>IGatekeeper</name>
+ <name>IGatekeeper</name>
<instance>default</instance>
</interface>
</hal>
diff --git a/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.rc b/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.rc
deleted file mode 100644
index 5413a6c..0000000
--- a/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.trusty
- class hal
- user system
- group system
diff --git a/trusty/gatekeeper/service.cpp b/trusty/gatekeeper/service.cpp
index c5ee488..d09804f 100644
--- a/trusty/gatekeeper/service.cpp
+++ b/trusty/gatekeeper/service.cpp
@@ -13,27 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.gatekeeper@1.0-service.trusty"
+#define LOG_TAG "android.hardware.gatekeeper-service.trusty"
#include <android-base/logging.h>
-#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
-
-#include <hidl/LegacySupport.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include "trusty_gatekeeper.h"
-// Generated HIDL files
-using android::hardware::gatekeeper::V1_0::IGatekeeper;
-using gatekeeper::TrustyGateKeeperDevice;
+using aidl::android::hardware::gatekeeper::TrustyGateKeeperDevice;
int main() {
- ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
- android::sp<TrustyGateKeeperDevice> gatekeeper(new TrustyGateKeeperDevice());
- auto status = gatekeeper->registerAsService();
- if (status != android::OK) {
- LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (trusty) (" << status << ")";
- }
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
- android::hardware::joinRpcThreadpool();
+ std::shared_ptr<TrustyGateKeeperDevice> gatekeeper =
+ ndk::SharedRefBase::make<TrustyGateKeeperDevice>();
+
+ const std::string instance = std::string() + TrustyGateKeeperDevice::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(gatekeeper->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+
return -1; // Should never get here.
}
diff --git a/trusty/gatekeeper/trusty_gatekeeper.cpp b/trusty/gatekeeper/trusty_gatekeeper.cpp
index ec4f81b..d0647df 100644
--- a/trusty/gatekeeper/trusty_gatekeeper.cpp
+++ b/trusty/gatekeeper/trusty_gatekeeper.cpp
@@ -16,28 +16,26 @@
#define LOG_TAG "TrustyGateKeeper"
-#include <android-base/logging.h>
+#include <endian.h>
#include <limits>
+#include <android-base/logging.h>
+#include <gatekeeper/password_handle.h>
+#include <hardware/hw_auth_token.h>
+
+#include "gatekeeper_ipc.h"
#include "trusty_gatekeeper.h"
#include "trusty_gatekeeper_ipc.h"
-#include "gatekeeper_ipc.h"
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
-using ::gatekeeper::EnrollRequest;
-using ::gatekeeper::EnrollResponse;
+namespace aidl::android::hardware::gatekeeper {
+
using ::gatekeeper::ERROR_INVALID;
-using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED;
using ::gatekeeper::ERROR_NONE;
using ::gatekeeper::ERROR_RETRY;
using ::gatekeeper::SizedBuffer;
using ::gatekeeper::VerifyRequest;
using ::gatekeeper::VerifyResponse;
-namespace gatekeeper {
-
constexpr const uint32_t SEND_BUF_SIZE = 8192;
constexpr const uint32_t RECV_BUF_SIZE = 8192;
@@ -54,89 +52,101 @@
trusty_gatekeeper_disconnect();
}
-SizedBuffer hidl_vec2sized_buffer(const hidl_vec<uint8_t>& vec) {
+SizedBuffer vec2sized_buffer(const std::vector<uint8_t>& vec) {
if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) return {};
auto buffer = new uint8_t[vec.size()];
std::copy(vec.begin(), vec.end(), buffer);
return {buffer, static_cast<uint32_t>(vec.size())};
}
-Return<void> TrustyGateKeeperDevice::enroll(uint32_t uid,
- const hidl_vec<uint8_t>& currentPasswordHandle,
- const hidl_vec<uint8_t>& currentPassword,
- const hidl_vec<uint8_t>& desiredPassword,
- enroll_cb _hidl_cb) {
+void sizedBuffer2AidlHWToken(SizedBuffer& buffer,
+ android::hardware::security::keymint::HardwareAuthToken* aidlToken) {
+ const hw_auth_token_t* authToken =
+ reinterpret_cast<const hw_auth_token_t*>(buffer.Data<uint8_t>());
+ aidlToken->challenge = authToken->challenge;
+ aidlToken->userId = authToken->user_id;
+ aidlToken->authenticatorId = authToken->authenticator_id;
+ // these are in network order: translate to host
+ aidlToken->authenticatorType =
+ static_cast<android::hardware::security::keymint::HardwareAuthenticatorType>(
+ be32toh(authToken->authenticator_type));
+ aidlToken->timestamp.milliSeconds = be64toh(authToken->timestamp);
+ aidlToken->mac.insert(aidlToken->mac.begin(), std::begin(authToken->hmac),
+ std::end(authToken->hmac));
+}
+
+::ndk::ScopedAStatus TrustyGateKeeperDevice::enroll(
+ int32_t uid, const std::vector<uint8_t>& currentPasswordHandle,
+ const std::vector<uint8_t>& currentPassword, const std::vector<uint8_t>& desiredPassword,
+ GatekeeperEnrollResponse* rsp) {
if (error_ != 0) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
}
if (desiredPassword.size() == 0) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
}
- EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle),
- hidl_vec2sized_buffer(desiredPassword),
- hidl_vec2sized_buffer(currentPassword));
+ EnrollRequest request(uid, vec2sized_buffer(currentPasswordHandle),
+ vec2sized_buffer(desiredPassword), vec2sized_buffer(currentPassword));
EnrollResponse response;
auto error = Send(request, &response);
if (error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else if (response.error == ERROR_RETRY) {
- _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
+ *rsp = {ERROR_RETRY_TIMEOUT, static_cast<int32_t>(response.retry_timeout), 0, {}};
+ return ndk::ScopedAStatus::ok();
} else if (response.error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else {
- hidl_vec<uint8_t> new_handle(response.enrolled_password_handle.Data<uint8_t>(),
- response.enrolled_password_handle.Data<uint8_t>() +
- response.enrolled_password_handle.size());
- _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle});
+ const ::gatekeeper::password_handle_t* password_handle =
+ response.enrolled_password_handle.Data<::gatekeeper::password_handle_t>();
+ *rsp = {STATUS_OK,
+ 0,
+ static_cast<int64_t>(password_handle->user_id),
+ {response.enrolled_password_handle.Data<uint8_t>(),
+ (response.enrolled_password_handle.Data<uint8_t>() +
+ response.enrolled_password_handle.size())}};
}
- return {};
+ return ndk::ScopedAStatus::ok();
}
-Return<void> TrustyGateKeeperDevice::verify(
- uint32_t uid, uint64_t challenge,
- const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
- const ::android::hardware::hidl_vec<uint8_t>& providedPassword, verify_cb _hidl_cb) {
+::ndk::ScopedAStatus TrustyGateKeeperDevice::verify(
+ int32_t uid, int64_t challenge, const std::vector<uint8_t>& enrolledPasswordHandle,
+ const std::vector<uint8_t>& providedPassword, GatekeeperVerifyResponse* rsp) {
if (error_ != 0) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
}
if (enrolledPasswordHandle.size() == 0) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
}
- VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle),
- hidl_vec2sized_buffer(providedPassword));
+ VerifyRequest request(uid, challenge, vec2sized_buffer(enrolledPasswordHandle),
+ vec2sized_buffer(providedPassword));
VerifyResponse response;
auto error = Send(request, &response);
if (error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else if (response.error == ERROR_RETRY) {
- _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
+ *rsp = {ERROR_RETRY_TIMEOUT, static_cast<int32_t>(response.retry_timeout), {}};
+ return ndk::ScopedAStatus::ok();
} else if (response.error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else {
- hidl_vec<uint8_t> auth_token(
- response.auth_token.Data<uint8_t>(),
- response.auth_token.Data<uint8_t>() + response.auth_token.size());
-
- _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL
- : GatekeeperStatusCode::STATUS_OK,
- response.retry_timeout, auth_token});
+ // On Success, return GatekeeperVerifyResponse with Success Status, timeout{0} and
+ // valid HardwareAuthToken.
+ *rsp = {response.request_reenroll ? STATUS_REENROLL : STATUS_OK, 0, {}};
+ // Convert the hw_auth_token_t to HardwareAuthToken in the response.
+ sizedBuffer2AidlHWToken(response.auth_token, &rsp->hardwareAuthToken);
}
- return {};
+ return ndk::ScopedAStatus::ok();
}
-Return<void> TrustyGateKeeperDevice::deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) {
+::ndk::ScopedAStatus TrustyGateKeeperDevice::deleteUser(int32_t uid) {
if (error_ != 0) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
}
DeleteUserRequest request(uid);
@@ -144,21 +154,19 @@
auto error = Send(request, &response);
if (error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else if (response.error == ERROR_NOT_IMPLEMENTED) {
- _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_NOT_IMPLEMENTED));
} else if (response.error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else {
- _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, {}});
+ return ndk::ScopedAStatus::ok();
}
- return {};
}
-Return<void> TrustyGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) {
+::ndk::ScopedAStatus TrustyGateKeeperDevice::deleteAllUsers() {
if (error_ != 0) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
- return {};
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
}
DeleteAllUsersRequest request;
@@ -166,16 +174,14 @@
auto error = Send(request, &response);
if (error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else if (response.error == ERROR_NOT_IMPLEMENTED) {
- _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_NOT_IMPLEMENTED));
} else if (response.error != ERROR_NONE) {
- _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
} else {
- _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, {}});
+ return ndk::ScopedAStatus::ok();
}
-
- return {};
}
gatekeeper_error_t TrustyGateKeeperDevice::Send(uint32_t command, const GateKeeperMessage& request,
@@ -201,4 +207,4 @@
return response->Deserialize(payload, payload + response_size);
}
-};
+} // namespace aidl::android::hardware::gatekeeper
diff --git a/trusty/gatekeeper/trusty_gatekeeper.h b/trusty/gatekeeper/trusty_gatekeeper.h
index 420dd7a..5cb5d4b 100644
--- a/trusty/gatekeeper/trusty_gatekeeper.h
+++ b/trusty/gatekeeper/trusty_gatekeeper.h
@@ -17,18 +17,30 @@
#ifndef TRUSTY_GATEKEEPER_H
#define TRUSTY_GATEKEEPER_H
-#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
-#include <hidl/Status.h>
-
#include <memory>
+#include <aidl/android/hardware/gatekeeper/BnGatekeeper.h>
+
#include <gatekeeper/gatekeeper_messages.h>
#include "gatekeeper_ipc.h"
-namespace gatekeeper {
+namespace aidl::android::hardware::gatekeeper {
-class TrustyGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper {
+using aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
+using aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
+using ::gatekeeper::DeleteAllUsersRequest;
+using ::gatekeeper::DeleteAllUsersResponse;
+using ::gatekeeper::DeleteUserRequest;
+using ::gatekeeper::DeleteUserResponse;
+using ::gatekeeper::EnrollRequest;
+using ::gatekeeper::EnrollResponse;
+using ::gatekeeper::gatekeeper_error_t;
+using ::gatekeeper::GateKeeperMessage;
+using ::gatekeeper::VerifyRequest;
+using ::gatekeeper::VerifyResponse;
+
+class TrustyGateKeeperDevice : public BnGatekeeper {
public:
explicit TrustyGateKeeperDevice();
~TrustyGateKeeperDevice();
@@ -40,11 +52,10 @@
* Returns: 0 on success or an error code less than 0 on error.
* On error, enrolled_password_handle will not be allocated.
*/
- ::android::hardware::Return<void> enroll(
- uint32_t uid, const ::android::hardware::hidl_vec<uint8_t>& currentPasswordHandle,
- const ::android::hardware::hidl_vec<uint8_t>& currentPassword,
- const ::android::hardware::hidl_vec<uint8_t>& desiredPassword,
- enroll_cb _hidl_cb) override;
+ ::ndk::ScopedAStatus enroll(int32_t uid, const std::vector<uint8_t>& currentPasswordHandle,
+ const std::vector<uint8_t>& currentPassword,
+ const std::vector<uint8_t>& desiredPassword,
+ GatekeeperEnrollResponse* _aidl_return) override;
/**
* Verifies provided_password matches enrolled_password_handle.
@@ -59,25 +70,24 @@
* Returns: 0 on success or an error code less than 0 on error
* On error, verification token will not be allocated
*/
- ::android::hardware::Return<void> verify(
- uint32_t uid, uint64_t challenge,
- const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
- const ::android::hardware::hidl_vec<uint8_t>& providedPassword,
- verify_cb _hidl_cb) override;
+ ::ndk::ScopedAStatus verify(int32_t uid, int64_t challenge,
+ const std::vector<uint8_t>& enrolledPasswordHandle,
+ const std::vector<uint8_t>& providedPassword,
+ GatekeeperVerifyResponse* _aidl_return) override;
- ::android::hardware::Return<void> deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override;
+ ::ndk::ScopedAStatus deleteAllUsers() override;
- ::android::hardware::Return<void> deleteAllUsers(deleteAllUsers_cb _hidl_cb) override;
+ ::ndk::ScopedAStatus deleteUser(int32_t uid) override;
private:
gatekeeper_error_t Send(uint32_t command, const GateKeeperMessage& request,
GateKeeperMessage* response);
- gatekeeper_error_t Send(const EnrollRequest& request, EnrollResponse *response) {
+ gatekeeper_error_t Send(const EnrollRequest& request, EnrollResponse* response) {
return Send(GK_ENROLL, request, response);
}
- gatekeeper_error_t Send(const VerifyRequest& request, VerifyResponse *response) {
+ gatekeeper_error_t Send(const VerifyRequest& request, VerifyResponse* response) {
return Send(GK_VERIFY, request, response);
}
@@ -93,7 +103,6 @@
int error_;
};
-} // namespace gatekeeper
+} // namespace aidl::android::hardware::gatekeeper
#endif
-
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 31f0a72..b249013 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -181,3 +181,30 @@
"-Werror",
],
}
+
+cc_binary {
+ name: "trusty_keymaster_set_attestation_ids",
+ vendor: true,
+
+ srcs: [
+ "set_attestation_ids/set_attestation_ids.cpp",
+ "ipc/trusty_keymaster_ipc.cpp",
+ ],
+
+ local_include_dirs: ["include"],
+
+ shared_libs: [
+ "libbase",
+ "libc",
+ "libcrypto",
+ "liblog",
+ "libtrusty",
+ "libhardware",
+ "libkeymaster_messages",
+ "libutils",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/trusty/keymaster/TEST_MAPPING b/trusty/keymaster/TEST_MAPPING
index ae48327..0475e04 100644
--- a/trusty/keymaster/TEST_MAPPING
+++ b/trusty/keymaster/TEST_MAPPING
@@ -1,13 +1,22 @@
{
"presubmit": [
{
- "name": "RemoteProvisionerUnitTests"
- },
- {
"name": "VtsAidlKeyMintTargetTest"
},
{
"name": "VtsHalRemotelyProvisionedComponentTargetTest"
+ },
+ {
+ "name": "RkpdAppUnitTests"
+ },
+ {
+ "name": "RkpdAppGoogleUnitTests"
+ },
+ {
+ "name": "RkpdAppIntegrationTests"
+ },
+ {
+ "name": "RkpdAppGoogleIntegrationTests"
}
]
}
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
index f767d40..09f696b 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
@@ -76,6 +76,7 @@
KM_CLEAR_ATTESTATION_CERT_CHAIN = (0xa000 << KEYMASTER_REQ_SHIFT),
KM_SET_WRAPPED_ATTESTATION_KEY = (0xb000 << KEYMASTER_REQ_SHIFT),
KM_SET_ATTESTATION_IDS = (0xc000 << KEYMASTER_REQ_SHIFT),
+ KM_SET_ATTESTATION_IDS_KM3 = (0xc001 << KEYMASTER_REQ_SHIFT),
KM_CONFIGURE_BOOT_PATCHLEVEL = (0xd000 << KEYMASTER_REQ_SHIFT),
};
diff --git a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
index 77dc854..3dc9c88 100644
--- a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
+++ b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.security.keymint</name>
- <version>2</version>
+ <version>3</version>
<fqname>IKeyMintDevice/default</fqname>
</hal>
<hal format="aidl">
diff --git a/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp b/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp
new file mode 100644
index 0000000..6b8f90f
--- /dev/null
+++ b/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2020 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 <getopt.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
+
+namespace {
+
+const char* sopts = "hb:d:p:s:M:m:i:c:";
+const struct option lopts[] = {
+ {"help", no_argument, nullptr, 'h'},
+ {"brand", required_argument, nullptr, 'b'},
+ {"device", required_argument, nullptr, 'd'},
+ {"product", required_argument, nullptr, 'p'},
+ {"serial", required_argument, nullptr, 's'},
+ {"manufacturer", required_argument, nullptr, 'M'},
+ {"model", required_argument, nullptr, 'm'},
+ {"imei", required_argument, nullptr, 'i'},
+ {"meid", required_argument, nullptr, 'c'},
+ {"imei2", required_argument, nullptr, '2'},
+ {0, 0, 0, 0},
+};
+
+std::string TELEPHONY_CMD_GET_IMEI = "cmd phone get-imei ";
+
+// Run a shell command and collect the output of it. If any error, set an empty string as the
+// output.
+std::string exec_command(const std::string& command) {
+ char buffer[128];
+ std::string result = "";
+
+ FILE* pipe = popen(command.c_str(), "r");
+ if (!pipe) {
+ fprintf(stderr, "popen('%s') failed\n", command.c_str());
+ return result;
+ }
+
+ while (!feof(pipe)) {
+ if (fgets(buffer, 128, pipe) != NULL) {
+ result += buffer;
+ }
+ }
+
+ pclose(pipe);
+ return result;
+}
+
+// Get IMEI using Telephony service shell command. If any error while executing the command
+// then empty string will be returned as output.
+std::string get_imei(int slot) {
+ std::string cmd = TELEPHONY_CMD_GET_IMEI + std::to_string(slot);
+ std::string output = exec_command(cmd);
+
+ if (output.empty()) {
+ fprintf(stderr, "Retrieve IMEI command ('%s') failed\n", cmd.c_str());
+ return "";
+ }
+
+ std::vector<std::string> out =
+ ::android::base::Tokenize(::android::base::Trim(output), "Device IMEI:");
+
+ if (out.size() != 1) {
+ fprintf(stderr, "Error parsing command ('%s') output '%s'\n", cmd.c_str(), output.c_str());
+ return "";
+ }
+
+ std::string imei = ::android::base::Trim(out[0]);
+ if (imei.compare("null") == 0) {
+ fprintf(stderr, "IMEI value from command ('%s') is null, skipping", cmd.c_str());
+ return "";
+ }
+ return imei;
+}
+
+std::string buf2string(const keymaster::Buffer& buf) {
+ return std::string(reinterpret_cast<const char*>(buf.peek_read()), buf.available_read());
+}
+
+void print_usage(const char* prog, const keymaster::SetAttestationIdsKM3Request& req) {
+ fprintf(stderr,
+ "Usage: %s [options]\n"
+ "\n"
+ "options:\n"
+ " -h, --help prints this message and exit\n"
+ " -b, --brand <val> set brand (default '%s')\n"
+ " -d, --device <val> set device (default '%s')\n"
+ " -p, --product <val> set product (default '%s')\n"
+ " -s, --serial <val> set serial (default '%s')\n"
+ " -M, --manufacturer <val> set manufacturer (default '%s')\n"
+ " -m, --model <val> set model (default '%s')\n"
+ " -i, --imei <val> set IMEI (default '%s')\n"
+ " -c, --meid <val> set MEID (default '%s')\n"
+ " -2, --imei2 <val> set second IMEI (default '%s')\n"
+ "\n",
+ prog, buf2string(req.base.brand).c_str(), buf2string(req.base.device).c_str(),
+ buf2string(req.base.product).c_str(), buf2string(req.base.serial).c_str(),
+ buf2string(req.base.manufacturer).c_str(), buf2string(req.base.model).c_str(),
+ buf2string(req.base.imei).c_str(), buf2string(req.base.meid).c_str(),
+ buf2string(req.second_imei).c_str());
+}
+
+void set_to(keymaster::Buffer* buf, const std::string& value) {
+ if (!value.empty()) {
+ buf->Reinitialize(value.data(), value.size());
+ }
+}
+
+void set_from_prop(keymaster::Buffer* buf, const std::string& prop) {
+ std::string prop_value = ::android::base::GetProperty(prop, /* default_value = */ "");
+ set_to(buf, prop_value);
+}
+
+void populate_base_ids(keymaster::SetAttestationIdsRequest* req) {
+ set_from_prop(&req->brand, "ro.product.brand");
+ set_from_prop(&req->device, "ro.product.device");
+ set_from_prop(&req->product, "ro.product.name");
+ set_from_prop(&req->serial, "ro.serialno");
+ set_from_prop(&req->manufacturer, "ro.product.manufacturer");
+ set_from_prop(&req->model, "ro.product.model");
+ std::string imei = get_imei(0);
+ set_to(&req->imei, imei);
+}
+
+void populate_ids(keymaster::SetAttestationIdsKM3Request* req) {
+ populate_base_ids(&req->base);
+
+ // - "What about IMEI?"
+ // - "You've already had it."
+ // - "We've had one, yes. What about second IMEI?"
+ // - "I don't think he knows about second IMEI, Pip."
+ std::string imei2 = get_imei(1);
+ set_to(&req->second_imei, imei2);
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ // By default, set attestation IDs to the values in userspace properties.
+ keymaster::SetAttestationIdsKM3Request req(/* ver = */ 4);
+ populate_ids(&req);
+
+ while (true) {
+ int oidx = 0;
+ int c = getopt_long(argc, argv, sopts, lopts, &oidx);
+ if (c == -1) {
+ break; /* done */
+ }
+
+ switch (c) {
+ case 'b':
+ req.base.brand.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'd':
+ req.base.device.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'p':
+ req.base.product.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 's':
+ req.base.serial.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'M':
+ req.base.manufacturer.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'm':
+ req.base.model.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'i':
+ req.base.imei.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'c':
+ req.base.meid.Reinitialize(optarg, strlen(optarg));
+ break;
+ case '2':
+ req.second_imei.Reinitialize(optarg, strlen(optarg));
+ break;
+ case 'h':
+ print_usage(argv[0], req);
+ exit(EXIT_SUCCESS);
+ default:
+ print_usage(argv[0], req);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (optind != argc) {
+ print_usage(argv[0], req);
+ exit(EXIT_FAILURE);
+ }
+
+ int ret = trusty_keymaster_connect();
+ if (ret) {
+ fprintf(stderr, "trusty_keymaster_connect failed: %d\n", ret);
+ return EXIT_FAILURE;
+ }
+
+ printf("Setting:\n"
+ " brand: %s\n"
+ " device: %s\n"
+ " product: %s\n"
+ " serial: %s\n"
+ " manufacturer: %s\n"
+ " model: %s\n"
+ " IMEI: %s\n"
+ " MEID: %s\n"
+ " SECOND_IMEI: %s\n\n",
+ buf2string(req.base.brand).c_str(), buf2string(req.base.device).c_str(),
+ buf2string(req.base.product).c_str(), buf2string(req.base.serial).c_str(),
+ buf2string(req.base.manufacturer).c_str(), buf2string(req.base.model).c_str(),
+ buf2string(req.base.imei).c_str(), buf2string(req.base.meid).c_str(),
+ buf2string(req.second_imei).c_str());
+ fflush(stdout);
+
+ keymaster::EmptyKeymasterResponse rsp(/* ver = */ 4);
+ const char* msg;
+ if (req.second_imei.available_read() == 0) {
+ // No SECOND_IMEI set, use base command.
+ ret = trusty_keymaster_send(KM_SET_ATTESTATION_IDS, req.base, &rsp);
+ msg = "SET_ATTESTATION_IDS";
+ } else {
+ // SECOND_IMEI is set, use updated command.
+ ret = trusty_keymaster_send(KM_SET_ATTESTATION_IDS_KM3, req, &rsp);
+ msg = "SET_ATTESTATION_IDS_KM3";
+ }
+ trusty_keymaster_disconnect();
+
+ if (ret) {
+ fprintf(stderr, "%s failed: %d\n", msg, ret);
+ return EXIT_FAILURE;
+ } else {
+ printf("done\n");
+ return EXIT_SUCCESS;
+ }
+}
diff --git a/trusty/keymint/Android.bp b/trusty/keymint/Android.bp
index 54aadaa..c19ebbd 100644
--- a/trusty/keymint/Android.bp
+++ b/trusty/keymint/Android.bp
@@ -13,6 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
rust_binary {
name: "android.hardware.security.keymint-service.rust.trusty",
relative_install_path: "hw",
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
index d2d5f27..cfa859f 100644
--- a/trusty/keymint/src/keymint_hal_main.rs
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -14,7 +14,9 @@
// limitations under the License.
//! This module implements the HAL service for Keymint (Rust) in Trusty.
-use kmr_hal::{keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel};
+use kmr_hal::{
+ extract_rsp, keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel,
+};
use log::{error, info};
use std::{
ffi::CString,
@@ -41,6 +43,7 @@
struct TipcChannel(trusty::TipcChannel);
impl SerializedChannel for TipcChannel {
+ const MAX_SIZE: usize = 4000;
fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
self.0.send(serialized_req).map_err(|e| {
binder::Status::new_exception(
@@ -54,21 +57,27 @@
),
)
})?;
- let mut recv_buf = Vec::new();
- // TODO(b/253501976): cope with fragmentation of responses
- self.0.recv(&mut recv_buf).map_err(|e| {
- binder::Status::new_exception(
- binder::ExceptionCode::TRANSACTION_FAILED,
- Some(
- &CString::new(format!(
- "Failed to receive the response via tipc channel because of {:?}",
- e
- ))
- .unwrap(),
- ),
- )
- })?;
- Ok(recv_buf)
+ let mut expect_more_msgs = true;
+ let mut full_rsp = Vec::new();
+ while expect_more_msgs {
+ let mut recv_buf = Vec::new();
+ self.0.recv(&mut recv_buf).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to receive the response via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ let current_rsp_content;
+ (expect_more_msgs, current_rsp_content) = extract_rsp(&recv_buf)?;
+ full_rsp.extend_from_slice(current_rsp_content);
+ }
+ Ok(full_rsp)
}
}
diff --git a/trusty/libtrusty/Android.bp b/trusty/libtrusty/Android.bp
index 086051d..9d94ec4 100644
--- a/trusty/libtrusty/Android.bp
+++ b/trusty/libtrusty/Android.bp
@@ -33,5 +33,6 @@
// TODO(b/170753563): cc_fuzz can't deal with vendor components. Build
// libtrusty for system and vendor.
vendor_available: true,
+ recovery_available: true,
defaults: ["libtrusty_defaults"],
}
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index eb0acb5..81c9881 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -596,6 +596,7 @@
TEST_PASSED = 0,
TEST_FAILED = 1,
TEST_MESSAGE = 2,
+ TEST_TEXT = 3,
};
int fd;
@@ -625,7 +626,7 @@
break;
} else if (rx_buf[0] == TEST_FAILED) {
break;
- } else if (rx_buf[0] == TEST_MESSAGE) {
+ } else if (rx_buf[0] == TEST_MESSAGE || rx_buf[0] == TEST_TEXT) {
write(STDOUT_FILENO, rx_buf + 1, ret - 1);
} else {
fprintf(stderr, "%s: Bad message header: %d\n", __func__, rx_buf[0]);
diff --git a/trusty/stats/aidl/Android.bp b/trusty/stats/aidl/Android.bp
new file mode 100644
index 0000000..078cc99
--- /dev/null
+++ b/trusty/stats/aidl/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+ name: "android.trusty.stats.nw.setter",
+ unstable: true,
+ vendor_available: true,
+ srcs: [
+ "android/trusty/stats/nw/setter/IStatsSetter.aidl",
+ ],
+ imports: ["android.frameworks.stats-V1"],
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ enabled: false,
+ platform_apis: false,
+ },
+ ndk: {
+ enabled: false,
+ },
+ },
+}
diff --git a/trusty/stats/aidl/android/trusty/stats/nw/setter/IStatsSetter.aidl b/trusty/stats/aidl/android/trusty/stats/nw/setter/IStatsSetter.aidl
new file mode 100644
index 0000000..f44f4a3
--- /dev/null
+++ b/trusty/stats/aidl/android/trusty/stats/nw/setter/IStatsSetter.aidl
@@ -0,0 +1,28 @@
+//
+// 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.
+//
+package android.trusty.stats.nw.setter;
+
+import android.frameworks.stats.IStats;
+
+interface IStatsSetter {
+ /**
+ * Set the IStats interface facet.
+ *
+ * @param istats The IStats facet provided by the caller for the remote
+ * service to report IStats' VendorAtom.
+ */
+ void setInterface(in IStats istats);
+}
diff --git a/trusty/stats/test/Android.bp b/trusty/stats/test/Android.bp
new file mode 100644
index 0000000..6b2bce9
--- /dev/null
+++ b/trusty/stats/test/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2021 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_test {
+ name: "trusty_stats_test",
+ vendor: true,
+ srcs: [
+ "stats_test.cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libtrusty",
+ "libbinder",
+ "libbinder_trusty",
+ "libutils",
+
+ // AIDL interface deps versions, please refer to below link
+ // https://source.android.com/docs/core/architecture/aidl/stable-aidl#module-naming-rules
+ "android.frameworks.stats-V1-cpp",
+ "android.trusty.stats.nw.setter-cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ require_root: true,
+ proprietary: true,
+}
diff --git a/trusty/stats/test/README.md b/trusty/stats/test/README.md
new file mode 100644
index 0000000..45e6af8
--- /dev/null
+++ b/trusty/stats/test/README.md
@@ -0,0 +1,97 @@
+# Development Notes
+
+* First get [repo_pull.py and gerrit.py](https://android.googlesource.com/platform/development/+/master/tools/repo_pull/) from aosp.
+
+* Although this repo is not currently in Trusty’s manifest, it’s sufficient to copy these two python scripts to the root of the Trusty project and run them from there. Make sure to follow the [repo_pull installation](https://android.googlesource.com/platform/development/+/master/tools/repo_pull/#installation) steps if necessary.
+
+## Build
+
+Build Android:
+
+```sh
+source build/envsetup.sh
+lunch qemu_trusty_arm64-userdebug
+m
+```
+
+Build Trusty:
+
+```sh
+./trusty/vendor/google/aosp/scripts/build.py qemu-generic-arm64-test-debug --skip-tests 2>stderr.log
+```
+
+## Trusty PORT_TEST
+
+On QEmu:
+
+```sh
+./build-root/build-qemu-generic-arm64-test-debug/run --headless --boot-test "com.android.trusty.stats.test" --verbose
+```
+
+On device: (Build for your device's debug target on both Adroid and Trusty)
+
+```sh
+/vendor/bin/trusty-ut-ctrl -D /dev/trusty-ipc-dev0 "com.android.trusty.stats.test"
+```
+
+On device, in a loop:
+
+```sh
+cat << 'EOF' > metrics.sh
+#!/system/bin/sh
+TIMES=${1:-0}
+X=0
+while [ "$TIMES" -eq 0 -o "$TIMES" -gt "$X" ]
+do
+ echo "######################## stats.test $X " $(( X++ ));
+ /vendor/bin/trusty-ut-ctrl -D /dev/trusty-ipc-dev0 "com.android.trusty.stats.test"
+done
+EOF
+
+adb wait-for-device
+adb push metrics.sh /data/user/test/metrics.sh
+adb shell sh /data/user/test/metrics.sh
+```
+
+## Android Native Test
+
+On QEmu:
+
+```sh
+./build-root/build-qemu-generic-arm64-test-debug/run --headless --android $ANDROID_PROJECT_ROOT --shell-command "/data/nativetest64/vendor/trusty_stats_test/trusty_stats_test" --verbose
+```
+
+On device: (Build for your device's debug target on both Adroid and Trusty)
+
+```sh
+/data/nativetest64/vendor/trusty_stats_test/trusty_stats_test
+```
+
+On device, in a loop:
+
+```sh
+cat << 'EOF' > metrics-nw.sh
+#!/system/bin/sh
+TIMES=${1:-0}
+X=0
+while [ "$TIMES" -eq 0 -o "$TIMES" -gt "$X" ]
+do
+ echo "######################## stats.test $X " $(( X++ ));
+ /data/nativetest64/vendor/trusty_stats_test/trusty_stats_test
+done
+EOF
+
+adb wait-for-device
+adb push metrics.sh /data/user/test/metrics-nw.sh
+adb shell sh /data/user/test/metrics-nw.sh
+```
+
+## Trusty Backtrace analysis
+
+
+```
+$ export A2L=./prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-addr2line
+$ export OD=./prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-objdump
+$ $OD -d -C build-root/build-qemu-generic-arm64-test-debug/user_tasks/trusty/user/base/app/metrics/metrics.syms.elf > objdump.lst
+$ $A2L -e build-root/build-qemu-generic-arm64-test-debug/user_tasks/trusty/user/base/app/metrics/metrics.syms.elf 0xe5104
+```
diff --git a/trusty/stats/test/stats_test.cpp b/trusty/stats/test/stats_test.cpp
new file mode 100644
index 0000000..1edddeb
--- /dev/null
+++ b/trusty/stats/test/stats_test.cpp
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+#include <errno.h>
+#include <getopt.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <condition_variable>
+#include <cstddef>
+#include <mutex>
+#include <queue>
+
+#include <android-base/expected.h>
+#include <android-base/logging.h>
+#include <android/frameworks/stats/BnStats.h>
+#include <android/frameworks/stats/IStats.h>
+#include <android/trusty/stats/nw/setter/IStatsSetter.h>
+#include <binder/RpcServer.h>
+#include <binder/RpcSession.h>
+#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTipcAndroid.h>
+#include <binder/RpcTrusty.h>
+#include <trusty/tipc.h>
+
+/** DOC:
+ * ./build-root/build-qemu-generic-arm64-test-debug/run \
+ * --android $ANDROID_PROJECT_ROOT \
+ * --headless --shell-command \
+ * "/data/nativetest64/vendor/trusty_stats_test/trusty_stats_test"
+ *
+ * adb -s emulator-5554 shell \
+ * /data/nativetest64/vendor/trusty_stats_test/trusty_stats_test
+ */
+using ::android::base::unique_fd;
+using ::android::binder::Status;
+using ::android::frameworks::stats::BnStats;
+using ::android::frameworks::stats::IStats;
+using ::android::frameworks::stats::VendorAtom;
+using ::android::frameworks::stats::VendorAtomValue;
+using ::android::trusty::stats::nw::setter::IStatsSetter;
+
+constexpr const char kTrustyDefaultDeviceName[] = "/dev/trusty-ipc-dev0";
+constexpr const char kTrustyStatsSetterTest[] =
+ "com.android.frameworks.stats.trusty.test.relayer.istats_setter";
+constexpr const char kTrustyStatsSetterMetrics[] =
+ "com.android.frameworks.stats.trusty.metrics.istats_setter";
+constexpr const char kTrustyStatsPortTest[] = "com.android.trusty.stats.test";
+constexpr const char kTrustyCrashPortTest[] = "com.android.trusty.crashtest";
+constexpr const char kTrustyCrasherUuid[] = "7ee4dddc-177a-420a-96ea-5d413d88228e:crasher";
+
+enum TrustyAtoms : int32_t {
+ TrustyAppCrashed = 100072,
+ TrustyError = 100145,
+ TrustyStorageError = 100146
+};
+
+enum TestMsgHeader : int32_t {
+ TEST_PASSED = 0,
+ TEST_FAILED = 1,
+ TEST_MESSAGE = 2,
+};
+
+namespace android {
+namespace trusty {
+namespace stats {
+
+class Stats : public BnStats {
+ public:
+ Stats() : BnStats() {}
+
+ Status reportVendorAtom(const VendorAtom& vendorAtom) override {
+ const char* atomIdStr = vendorAtomStr(vendorAtom.atomId);
+ ALOGD("Vendor atom reported of type: %s\n", atomIdStr);
+ std::lock_guard lock(mLock);
+ mQueueVendorAtom.push(vendorAtom);
+ mCondVar.notify_one();
+ return Status::ok();
+ }
+
+ status_t getVendorAtom(VendorAtom* pVendorAtom, int64_t waitForMs) {
+ std::unique_lock lock(mLock);
+ while (mQueueVendorAtom.empty()) {
+ auto rc = mCondVar.wait_for(lock, std::chrono::milliseconds(waitForMs));
+ if (rc == std::cv_status::timeout) {
+ return TIMED_OUT;
+ }
+ }
+ *pVendorAtom = mQueueVendorAtom.front();
+ mQueueVendorAtom.pop();
+ return NO_ERROR;
+ }
+
+ private:
+ const char* vendorAtomStr(int32_t atomId) {
+ switch (atomId) {
+ case TrustyAtoms::TrustyAppCrashed:
+ return "TrustyAtoms::TrustyAppCrashed";
+ case TrustyAtoms::TrustyError:
+ return "TrustyAtoms::TrustyError";
+ case TrustyAtoms::TrustyStorageError:
+ return "TrustyAtoms::TrustyStorageError";
+ default:
+ return "unknown TrustyAtoms type";
+ }
+ }
+ std::mutex mLock;
+ std::condition_variable mCondVar;
+ std::queue<VendorAtom> mQueueVendorAtom;
+};
+
+class TrustyStatsTestBase : public ::testing::Test {
+ protected:
+ TrustyStatsTestBase(std::string&& portNameStatsSetter, std::string&& portNamePortTest)
+ : mPortTestFd(-1),
+ mPortNameStatsSetter(std::move(portNameStatsSetter)),
+ mPortNamePortTest(std::move(portNamePortTest)) {}
+
+ void SetUp() override {
+ // Commenting out the server portion because we do not have any direct
+ // incoming call Calls from TA are currently being handled on the mSession's
+ // extra thread. android::sp<::android::RpcServer> server =
+ // ::android::RpcServer::make(::android::RpcTransportCtxFactoryRaw::make());
+
+ mStats = android::sp<Stats>::make();
+ // Increasing number of incoming threads on mSession to be able to receive
+ // callbacks
+ auto session_initializer = [](sp<RpcSession>& session) {
+ session->setMaxIncomingThreads(1);
+ };
+
+ ASSERT_FALSE(mSession);
+ mSession = RpcTrustyConnectWithSessionInitializer(
+ kTrustyDefaultDeviceName, mPortNameStatsSetter.c_str(), session_initializer);
+ ASSERT_TRUE(mSession);
+
+ auto root = mSession->getRootObject();
+ ASSERT_TRUE(root);
+ auto statsSetter = IStatsSetter::asInterface(root);
+ ASSERT_TRUE(statsSetter);
+ statsSetter->setInterface(mStats);
+ }
+ void TearDown() override {
+ // close connection to unitest app
+ if (mPortTestFd != -1) {
+ tipc_close(mPortTestFd);
+ }
+ mPortTestFd = -1;
+
+ if (mSession) {
+ // shutdownAndWait here races with sending out the DecStrong
+ // messages after reportVendorAtom returns, so we delay it a little
+ // bit to give the messages time to go out over the transport
+ usleep(50000);
+ ASSERT_TRUE(mSession->shutdownAndWait(true));
+ }
+ mSession.clear();
+ mStats.clear();
+ }
+ void StartPortTest() {
+ // connect to unitest app
+ mPortTestFd = tipc_connect(kTrustyDefaultDeviceName, mPortNamePortTest.c_str());
+ if (mPortTestFd < 0) {
+ ALOGE("Failed to connect to '%s' app: %s\n", kTrustyStatsPortTest,
+ strerror(-mPortTestFd));
+ }
+ ASSERT_GT(mPortTestFd, 0);
+ }
+ void WaitPortTestDone() {
+ // wait for test to complete
+ char rxBuf[1024];
+ const char prolog[] = "Trusty PORT_TEST:";
+ strncpy(rxBuf, prolog, sizeof(prolog) - 1);
+ char* pRxBuf = rxBuf + sizeof(prolog) - 1;
+ size_t remainingBufSize = sizeof(rxBuf) - sizeof(prolog) - 1;
+
+ ASSERT_NE(mPortTestFd, -1);
+ for (;;) {
+ int rc = read(mPortTestFd, pRxBuf, remainingBufSize);
+ ASSERT_GT(rc, 0);
+ ASSERT_LT(rc, (int)remainingBufSize);
+ if (pRxBuf[0] == TEST_PASSED) {
+ break;
+ } else if (pRxBuf[0] == TEST_FAILED) {
+ break;
+ } else if (pRxBuf[0] == TEST_MESSAGE) {
+ pRxBuf[0] = ' ';
+ write(STDOUT_FILENO, rxBuf, rc + sizeof(prolog) - 1);
+ } else {
+ ALOGE("Bad message header: %d\n", rxBuf[0]);
+ break;
+ }
+ }
+ ASSERT_EQ(pRxBuf[0], TEST_PASSED);
+ }
+
+ android::sp<Stats> mStats;
+
+ private:
+ android::sp<RpcSession> mSession;
+ int mPortTestFd;
+ std::string mPortNameStatsSetter;
+ std::string mPortNamePortTest;
+};
+
+class TrustyStatsTest : public TrustyStatsTestBase {
+ protected:
+ TrustyStatsTest() : TrustyStatsTestBase(kTrustyStatsSetterTest, kTrustyStatsPortTest) {}
+};
+
+class TrustyMetricsCrashTest : public TrustyStatsTestBase {
+ protected:
+ TrustyMetricsCrashTest()
+ : TrustyStatsTestBase(kTrustyStatsSetterMetrics, kTrustyCrashPortTest) {}
+};
+
+TEST_F(TrustyStatsTest, CheckAtoms) {
+ int atomAppCrashedCnt = 0;
+ int atomStorageErrorCnt = 0;
+ int atomTrustyErrorCnt = 0;
+ uint64_t blockForMs = 500;
+ StartPortTest();
+ WaitPortTestDone();
+ for (;;) {
+ VendorAtom vendorAtom;
+ auto status = mStats->getVendorAtom(&vendorAtom, blockForMs);
+ ASSERT_THAT(status, ::testing::AnyOf(NO_ERROR, TIMED_OUT));
+ if (status == TIMED_OUT) {
+ // No more atoms
+ break;
+ }
+
+ ASSERT_THAT(vendorAtom.atomId,
+ ::testing::AnyOf(::testing::Eq(TrustyAtoms::TrustyAppCrashed),
+ ::testing::Eq(TrustyAtoms::TrustyError),
+ ::testing::Eq(TrustyAtoms::TrustyStorageError)));
+ ASSERT_STREQ(String8(vendorAtom.reverseDomainName), "google.android.trusty");
+ switch (vendorAtom.atomId) {
+ case TrustyAtoms::TrustyAppCrashed:
+ ++atomAppCrashedCnt;
+ ASSERT_STREQ(String8(vendorAtom.values[0].get<VendorAtomValue::stringValue>()),
+ "5247d19b-cf09-4272-a450-3ef20dbefc14");
+ break;
+ case TrustyAtoms::TrustyStorageError:
+ ++atomStorageErrorCnt;
+ ASSERT_EQ(vendorAtom.values[0].get<VendorAtomValue::intValue>(), 5);
+ ASSERT_STREQ(String8(vendorAtom.values[1].get<VendorAtomValue::stringValue>()),
+ "5247d19b-cf09-4272-a450-3ef20dbefc14");
+ ASSERT_STREQ(String8(vendorAtom.values[2].get<VendorAtomValue::stringValue>()),
+ "5247d19b-cf09-4272-a450-3ef20dbefc14");
+ ASSERT_EQ(vendorAtom.values[3].get<VendorAtomValue::intValue>(), 1);
+ ASSERT_EQ(vendorAtom.values[4].get<VendorAtomValue::intValue>(), 3);
+ ASSERT_EQ(vendorAtom.values[5].get<VendorAtomValue::longValue>(),
+ 0x4BCDEFABBAFEDCBALL);
+ ASSERT_EQ(vendorAtom.values[6].get<VendorAtomValue::intValue>(), 4);
+ ASSERT_EQ(vendorAtom.values[7].get<VendorAtomValue::longValue>(), 1023);
+ break;
+ case TrustyAtoms::TrustyError:
+ ++atomTrustyErrorCnt;
+ break;
+ default:
+ FAIL() << "Unknown vendor atom ID: " << vendorAtom.atomId;
+ break;
+ }
+ };
+ ASSERT_EQ(atomAppCrashedCnt, 1);
+ ASSERT_EQ(atomStorageErrorCnt, 1);
+ ASSERT_EQ(atomTrustyErrorCnt, 0);
+}
+
+TEST_F(TrustyMetricsCrashTest, CheckTrustyCrashAtoms) {
+ const std::vector<uint32_t> kExpectedCrashReasonsArm64{
+ 0x00000001U, // exit_failure (twice)
+ 0x00000001U,
+ 0x92000004U, // read_null_ptr
+ 0xf200002aU, // brk_instruction
+ 0x92000004U, // read_bad_ptr
+ 0x92000044U, // crash_write_bad_ptr
+ 0x9200004fU, // crash_write_ro_ptr
+ 0x8200000fU, // crash_exec_rodata
+ 0x8200000fU, // crash_exec_data
+ };
+ const std::vector<uint32_t> kExpectedCrashReasonsArm32{
+ 0x00000001U, // exit_failure (twice)
+ 0x00000001U,
+ 0x20000007U, // read_null_ptr
+ 0x20000007U, // read_bad_ptr
+ 0x20000807U, // crash_write_bad_ptr
+ 0x2000080fU, // crash_write_ro_ptr
+ 0x3000000fU, // crash_exec_rodata
+ 0x3000000fU, // crash_exec_data
+ };
+
+ int expectedAtomCnt = 7;
+ int atomAppCrashedCnt = 0;
+ int atomStorageErrorCnt = 0;
+ int atomTrustyErrorCnt = 0;
+ std::vector<uint32_t> atomCrashReasons;
+ uint64_t blockForMs = 500;
+ StartPortTest();
+ WaitPortTestDone();
+ for (;;) {
+ VendorAtom vendorAtom;
+ auto status = mStats->getVendorAtom(&vendorAtom, blockForMs);
+ ASSERT_THAT(status, ::testing::AnyOf(NO_ERROR, TIMED_OUT));
+ if (status == TIMED_OUT) {
+ // No more atoms
+ break;
+ }
+
+ ASSERT_THAT(vendorAtom.atomId,
+ ::testing::AnyOf(::testing::Eq(TrustyAtoms::TrustyAppCrashed),
+ ::testing::Eq(TrustyAtoms::TrustyError),
+ ::testing::Eq(TrustyAtoms::TrustyStorageError)));
+ ASSERT_STREQ(String8(vendorAtom.reverseDomainName), "google.android.trusty");
+
+ switch (vendorAtom.atomId) {
+ case TrustyAtoms::TrustyAppCrashed:
+ ++atomAppCrashedCnt;
+ ASSERT_STREQ(String8(vendorAtom.values[0].get<VendorAtomValue::stringValue>()),
+ kTrustyCrasherUuid);
+ atomCrashReasons.push_back(vendorAtom.values[1].get<VendorAtomValue::intValue>());
+ break;
+ case TrustyAtoms::TrustyStorageError:
+ ++atomStorageErrorCnt;
+ break;
+ case TrustyAtoms::TrustyError:
+ ++atomTrustyErrorCnt;
+ ASSERT_STREQ(String8(vendorAtom.values[1].get<VendorAtomValue::stringValue>()), "");
+ break;
+ default:
+ FAIL() << "Unknown vendor atom ID: " << vendorAtom.atomId;
+ }
+ }
+ ASSERT_GE(atomAppCrashedCnt, expectedAtomCnt - 1);
+ ASSERT_EQ(atomStorageErrorCnt, 0);
+ // There is one dropped event left over from Trusty boot,
+ // it may show up here
+ ASSERT_LE(atomTrustyErrorCnt, 1);
+ ASSERT_THAT(atomCrashReasons,
+ ::testing::AnyOf(kExpectedCrashReasonsArm64, kExpectedCrashReasonsArm32));
+};
+
+} // namespace stats
+} // namespace trusty
+} // namespace android
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
index e952ee0..2e97ee0 100644
--- a/trusty/storage/proxy/Android.bp
+++ b/trusty/storage/proxy/Android.bp
@@ -28,6 +28,7 @@
"rpmb.c",
"storage.c",
"proxy.c",
+ "watchdog.cpp",
],
shared_libs: [
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index b970406..c89c5b6 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -31,6 +31,7 @@
#include "log.h"
#include "rpmb.h"
#include "storage.h"
+#include "watchdog.h"
#define REQ_BUFFER_SIZE 4096
static uint8_t req_buffer[REQ_BUFFER_SIZE + 1];
@@ -73,6 +74,8 @@
static int handle_req(struct storage_msg* msg, const void* req, size_t req_len) {
int rc;
+ struct watcher* watcher = watch_start("request", msg);
+
if ((msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) && msg->cmd != STORAGE_RPMB_SEND &&
msg->cmd != STORAGE_FILE_WRITE) {
/*
@@ -81,14 +84,14 @@
*/
ALOGE("cmd 0x%x: post commit option is not implemented\n", msg->cmd);
msg->result = STORAGE_ERR_UNIMPLEMENTED;
- return ipc_respond(msg, NULL, 0);
+ goto err_response;
}
if (msg->flags & STORAGE_MSG_FLAG_PRE_COMMIT) {
- rc = storage_sync_checkpoint();
+ rc = storage_sync_checkpoint(watcher);
if (rc < 0) {
msg->result = STORAGE_ERR_SYNC_FAILURE;
- return ipc_respond(msg, NULL, 0);
+ goto err_response;
}
}
@@ -99,57 +102,65 @@
if (rc != 0) {
ALOGE("is_data_checkpoint_active failed in an unexpected way. Aborting.\n");
msg->result = STORAGE_ERR_GENERIC;
- return ipc_respond(msg, NULL, 0);
+ goto err_response;
} else if (is_checkpoint_active) {
ALOGE("Checkpoint in progress, dropping write ...\n");
msg->result = STORAGE_ERR_GENERIC;
- return ipc_respond(msg, NULL, 0);
+ goto err_response;
}
}
switch (msg->cmd) {
case STORAGE_FILE_DELETE:
- rc = storage_file_delete(msg, req, req_len);
+ rc = storage_file_delete(msg, req, req_len, watcher);
break;
case STORAGE_FILE_OPEN:
- rc = storage_file_open(msg, req, req_len);
+ rc = storage_file_open(msg, req, req_len, watcher);
break;
case STORAGE_FILE_CLOSE:
- rc = storage_file_close(msg, req, req_len);
+ rc = storage_file_close(msg, req, req_len, watcher);
break;
case STORAGE_FILE_WRITE:
- rc = storage_file_write(msg, req, req_len);
+ rc = storage_file_write(msg, req, req_len, watcher);
break;
case STORAGE_FILE_READ:
- rc = storage_file_read(msg, req, req_len);
+ rc = storage_file_read(msg, req, req_len, watcher);
break;
case STORAGE_FILE_GET_SIZE:
- rc = storage_file_get_size(msg, req, req_len);
+ rc = storage_file_get_size(msg, req, req_len, watcher);
break;
case STORAGE_FILE_SET_SIZE:
- rc = storage_file_set_size(msg, req, req_len);
+ rc = storage_file_set_size(msg, req, req_len, watcher);
+ break;
+
+ case STORAGE_FILE_GET_MAX_SIZE:
+ rc = storage_file_get_max_size(msg, req, req_len, watcher);
break;
case STORAGE_RPMB_SEND:
- rc = rpmb_send(msg, req, req_len);
+ rc = rpmb_send(msg, req, req_len, watcher);
break;
default:
ALOGE("unhandled command 0x%x\n", msg->cmd);
msg->result = STORAGE_ERR_UNIMPLEMENTED;
- rc = 1;
+ goto err_response;
}
- if (rc > 0) {
- /* still need to send response */
- rc = ipc_respond(msg, NULL, 0);
- }
+ /* response was sent in handler */
+ goto finish;
+
+err_response:
+ rc = ipc_respond(msg, NULL, 0);
+
+finish:
+ watch_finish(watcher);
return rc;
}
diff --git a/trusty/storage/proxy/rpmb.c b/trusty/storage/proxy/rpmb.c
index b1b8232..22a85a7 100644
--- a/trusty/storage/proxy/rpmb.c
+++ b/trusty/storage/proxy/rpmb.c
@@ -321,7 +321,8 @@
return SCSI_RES_ERR;
}
-static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req) {
+static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req,
+ struct watcher* watcher) {
union {
struct mmc_ioc_multi_cmd multi;
uint8_t raw[sizeof(struct mmc_ioc_multi_cmd) + sizeof(struct mmc_ioc_cmd) * 3];
@@ -375,14 +376,17 @@
cmd++;
}
+ watch_progress(watcher, "rpmb mmc ioctl");
rc = ioctl(mmc_fd, MMC_IOC_MULTI_CMD, &mmc.multi);
+ watch_progress(watcher, "rpmb mmc ioctl done");
if (rc < 0) {
ALOGE("%s: mmc ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
}
return rc;
}
-static int send_ufs_rpmb_req(int sg_fd, const struct storage_rpmb_send_req* req) {
+static int send_ufs_rpmb_req(int sg_fd, const struct storage_rpmb_send_req* req,
+ struct watcher* watcher) {
int rc;
int wl_rc;
const uint8_t* write_buf = req->payload;
@@ -410,7 +414,9 @@
set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
req->reliable_write_size, (void*)write_buf, (unsigned char*)&out_cdb,
sense_buffer);
+ watch_progress(watcher, "rpmb ufs reliable write");
rc = ioctl(sg_fd, SG_IO, &io_hdr);
+ watch_progress(watcher, "rpmb ufs reliable write done");
if (rc < 0) {
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
goto err_op;
@@ -435,7 +441,9 @@
set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
req->write_size, (void*)write_buf, (unsigned char*)&out_cdb,
sense_buffer);
+ watch_progress(watcher, "rpmb ufs write");
rc = ioctl(sg_fd, SG_IO, &io_hdr);
+ watch_progress(watcher, "rpmb ufs write done");
if (rc < 0) {
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
goto err_op;
@@ -450,7 +458,9 @@
sg_io_hdr_t io_hdr;
set_sg_io_hdr(&io_hdr, SG_DXFER_FROM_DEV, sizeof(in_cdb), sizeof(sense_buffer),
req->read_size, read_buf, (unsigned char*)&in_cdb, sense_buffer);
+ watch_progress(watcher, "rpmb ufs read");
rc = ioctl(sg_fd, SG_IO, &io_hdr);
+ watch_progress(watcher, "rpmb ufs read done");
if (rc < 0) {
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
}
@@ -487,7 +497,7 @@
return rc;
}
-int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
+int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len, struct watcher* watcher) {
int rc;
const struct storage_rpmb_send_req* req = r;
@@ -523,13 +533,13 @@
}
if (dev_type == MMC_RPMB) {
- rc = send_mmc_rpmb_req(rpmb_fd, req);
+ rc = send_mmc_rpmb_req(rpmb_fd, req, watcher);
if (rc < 0) {
msg->result = STORAGE_ERR_GENERIC;
goto err_response;
}
} else if (dev_type == UFS_RPMB) {
- rc = send_ufs_rpmb_req(rpmb_fd, req);
+ rc = send_ufs_rpmb_req(rpmb_fd, req, watcher);
if (rc < 0) {
ALOGE("send_ufs_rpmb_req failed: %d, %s\n", rc, strerror(errno));
msg->result = STORAGE_ERR_GENERIC;
diff --git a/trusty/storage/proxy/rpmb.h b/trusty/storage/proxy/rpmb.h
index f4e1b51..04bdf9a 100644
--- a/trusty/storage/proxy/rpmb.h
+++ b/trusty/storage/proxy/rpmb.h
@@ -18,8 +18,10 @@
#include <stdint.h>
#include <trusty/interface/storage.h>
+#include "watchdog.h"
+
enum dev_type { UNKNOWN_RPMB, MMC_RPMB, VIRT_RPMB, UFS_RPMB, SOCK_RPMB };
int rpmb_open(const char* rpmb_devname, enum dev_type dev_type);
-int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len);
+int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len, struct watcher* watcher);
void rpmb_close(void);
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index 033dc21..2299481 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
+#include <linux/fs.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -30,12 +31,16 @@
#include "ipc.h"
#include "log.h"
#include "storage.h"
+#include "watchdog.h"
#define FD_TBL_SIZE 64
#define MAX_READ_SIZE 4096
#define ALTERNATE_DATA_DIR "alternate/"
+/* Maximum file size for filesystem backed storage (i.e. not block dev backed storage) */
+#define MAX_FILE_SIZE (0x10000000000)
+
enum sync_state {
SS_UNUSED = -1,
SS_CLEAN = 0,
@@ -176,9 +181,8 @@
return rcnt;
}
-int storage_file_delete(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
+int storage_file_delete(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
char *path = NULL;
const struct storage_file_delete_req *req = r;
@@ -204,6 +208,7 @@
goto err_response;
}
+ watch_progress(watcher, "unlinking file");
rc = unlink(path);
if (rc < 0) {
rc = errno;
@@ -227,8 +232,9 @@
return ipc_respond(msg, NULL, 0);
}
-static void sync_parent(const char* path) {
+static void sync_parent(const char* path, struct watcher* watcher) {
int parent_fd;
+ watch_progress(watcher, "syncing parent");
char* parent_path = dirname(path);
parent_fd = TEMP_FAILURE_RETRY(open(parent_path, O_RDONLY));
if (parent_fd >= 0) {
@@ -238,9 +244,11 @@
ALOGE("%s: failed to open parent directory \"%s\" for sync: %s\n", __func__, parent_path,
strerror(errno));
}
+ watch_progress(watcher, "done syncing parent");
}
-int storage_file_open(struct storage_msg* msg, const void* r, size_t req_len) {
+int storage_file_open(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
char* path = NULL;
const struct storage_file_open_req *req = r;
struct storage_file_open_resp resp = {0};
@@ -302,7 +310,7 @@
char* parent_path = dirname(path);
rc = mkdir(parent_path, S_IRWXU);
if (rc == 0) {
- sync_parent(parent_path);
+ sync_parent(parent_path, watcher);
} else if (errno != EEXIST) {
ALOGE("%s: Could not create parent directory \"%s\": %s\n", __func__, parent_path,
strerror(errno));
@@ -343,7 +351,7 @@
}
if (open_flags & O_CREAT) {
- sync_parent(path);
+ sync_parent(path, watcher);
}
free(path);
@@ -371,9 +379,8 @@
return ipc_respond(msg, NULL, 0);
}
-int storage_file_close(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
+int storage_file_close(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
const struct storage_file_close_req *req = r;
if (req_len != sizeof(*req)) {
@@ -386,7 +393,9 @@
int fd = remove_fd(req->handle);
ALOGV("%s: handle = %u: fd = %u\n", __func__, req->handle, fd);
+ watch_progress(watcher, "fsyncing before file close");
int rc = fsync(fd);
+ watch_progress(watcher, "done fsyncing before file close");
if (rc < 0) {
rc = errno;
ALOGE("%s: fsync failed for fd=%u: %s\n",
@@ -410,10 +419,8 @@
return ipc_respond(msg, NULL, 0);
}
-
-int storage_file_write(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
+int storage_file_write(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
int rc;
const struct storage_file_write_req *req = r;
@@ -425,17 +432,20 @@
}
int fd = lookup_fd(req->handle, true);
+ watch_progress(watcher, "writing");
if (write_with_retry(fd, &req->data[0], req_len - sizeof(*req),
req->offset) < 0) {
+ watch_progress(watcher, "writing done w/ error");
rc = errno;
ALOGW("%s: error writing file (fd=%d): %s\n",
__func__, fd, strerror(errno));
msg->result = translate_errno(rc);
goto err_response;
}
+ watch_progress(watcher, "writing done");
if (msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) {
- rc = storage_sync_checkpoint();
+ rc = storage_sync_checkpoint(watcher);
if (rc < 0) {
msg->result = STORAGE_ERR_SYNC_FAILURE;
goto err_response;
@@ -448,10 +458,8 @@
return ipc_respond(msg, NULL, 0);
}
-
-int storage_file_read(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
+int storage_file_read(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
int rc;
const struct storage_file_read_req *req = r;
@@ -470,8 +478,10 @@
}
int fd = lookup_fd(req->handle, false);
+ watch_progress(watcher, "reading");
ssize_t read_res = read_with_retry(fd, read_rsp.hdr.data, req->size,
(off_t)req->offset);
+ watch_progress(watcher, "reading done");
if (read_res < 0) {
rc = errno;
ALOGW("%s: error reading file (fd=%d): %s\n",
@@ -487,10 +497,8 @@
return ipc_respond(msg, NULL, 0);
}
-
-int storage_file_get_size(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
+int storage_file_get_size(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
const struct storage_file_get_size_req *req = r;
struct storage_file_get_size_resp resp = {0};
@@ -503,7 +511,9 @@
struct stat stat;
int fd = lookup_fd(req->handle, false);
+ watch_progress(watcher, "fstat");
int rc = fstat(fd, &stat);
+ watch_progress(watcher, "fstat done");
if (rc < 0) {
rc = errno;
ALOGE("%s: error stat'ing file (fd=%d): %s\n",
@@ -520,10 +530,8 @@
return ipc_respond(msg, NULL, 0);
}
-
-int storage_file_set_size(struct storage_msg *msg,
- const void *r, size_t req_len)
-{
+int storage_file_set_size(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
const struct storage_file_set_size_req *req = r;
if (req_len != sizeof(*req)) {
@@ -534,7 +542,9 @@
}
int fd = lookup_fd(req->handle, true);
+ watch_progress(watcher, "ftruncate");
int rc = TEMP_FAILURE_RETRY(ftruncate(fd, req->size));
+ watch_progress(watcher, "ftruncate done");
if (rc < 0) {
rc = errno;
ALOGE("%s: error truncating file (fd=%d): %s\n",
@@ -549,6 +559,48 @@
return ipc_respond(msg, NULL, 0);
}
+int storage_file_get_max_size(struct storage_msg* msg, const void* r, size_t req_len,
+ struct watcher* watcher) {
+ const struct storage_file_get_max_size_req* req = r;
+ struct storage_file_get_max_size_resp resp = {0};
+ uint64_t max_size = 0;
+
+ if (req_len != sizeof(*req)) {
+ ALOGE("%s: invalid request length (%zd != %zd)\n", __func__, req_len, sizeof(*req));
+ msg->result = STORAGE_ERR_NOT_VALID;
+ goto err_response;
+ }
+
+ struct stat stat;
+ int fd = lookup_fd(req->handle, false);
+ watch_progress(watcher, "fstat to get max size");
+ int rc = fstat(fd, &stat);
+ watch_progress(watcher, "fstat to get max size done");
+ if (rc < 0) {
+ ALOGE("%s: error stat'ing file (fd=%d): %s\n", __func__, fd, strerror(errno));
+ goto err_response;
+ }
+
+ if ((stat.st_mode & S_IFMT) == S_IFBLK) {
+ rc = ioctl(fd, BLKGETSIZE64, &max_size);
+ if (rc < 0) {
+ rc = errno;
+ ALOGE("%s: error calling ioctl on file (fd=%d): %s\n", __func__, fd, strerror(errno));
+ msg->result = translate_errno(rc);
+ goto err_response;
+ }
+ } else {
+ max_size = MAX_FILE_SIZE;
+ }
+
+ resp.max_size = max_size;
+ msg->result = STORAGE_NO_ERROR;
+ return ipc_respond(msg, &resp, sizeof(resp));
+
+err_response:
+ return ipc_respond(msg, NULL, 0);
+}
+
int storage_init(const char *dirname)
{
/* If there is an active DSU image, use the alternate fs mode. */
@@ -563,10 +615,10 @@
return 0;
}
-int storage_sync_checkpoint(void)
-{
+int storage_sync_checkpoint(struct watcher* watcher) {
int rc;
+ watch_progress(watcher, "sync fd table");
/* sync fd table and reset it to clean state first */
for (uint fd = 0; fd < FD_TBL_SIZE; fd++) {
if (fd_state[fd] == SS_DIRTY) {
@@ -591,10 +643,12 @@
* because our fd table is large enough to handle the few open files we
* use.
*/
- sync();
- fs_state = SS_CLEAN;
+ watch_progress(watcher, "all fs sync");
+ sync();
+ fs_state = SS_CLEAN;
}
+ watch_progress(watcher, "done syncing");
+
return 0;
}
-
diff --git a/trusty/storage/proxy/storage.h b/trusty/storage/proxy/storage.h
index 5a670d4..f29fdf2 100644
--- a/trusty/storage/proxy/storage.h
+++ b/trusty/storage/proxy/storage.h
@@ -18,28 +18,33 @@
#include <stdint.h>
#include <trusty/interface/storage.h>
-int storage_file_delete(struct storage_msg *msg,
- const void *req, size_t req_len);
+/* Defined in watchdog.h */
+struct watcher;
-int storage_file_open(struct storage_msg *msg,
- const void *req, size_t req_len);
+int storage_file_delete(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_file_close(struct storage_msg *msg,
- const void *req, size_t req_len);
+int storage_file_open(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_file_write(struct storage_msg *msg,
- const void *req, size_t req_len);
+int storage_file_close(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_file_read(struct storage_msg *msg,
- const void *req, size_t req_len);
+int storage_file_write(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_file_get_size(struct storage_msg *msg,
- const void *req, size_t req_len);
+int storage_file_read(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_file_set_size(struct storage_msg *msg,
- const void *req, size_t req_len);
+int storage_file_get_size(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_init(const char *dirname);
+int storage_file_set_size(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
-int storage_sync_checkpoint(void);
+int storage_file_get_max_size(struct storage_msg* msg, const void* req, size_t req_len,
+ struct watcher* watcher);
+int storage_init(const char* dirname);
+
+int storage_sync_checkpoint(struct watcher* watcher);
diff --git a/trusty/storage/proxy/watchdog.cpp b/trusty/storage/proxy/watchdog.cpp
new file mode 100644
index 0000000..6c09e26
--- /dev/null
+++ b/trusty/storage/proxy/watchdog.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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 "watchdog.h"
+
+#include <chrono>
+#include <cstdint>
+#include <optional>
+#include <thread>
+#include <vector>
+
+#include <android-base/logging.h>
+
+struct watcher {
+ watcher(const char* id, const struct storage_msg* request);
+ void SetState(const char* new_state);
+ void LogTimeout();
+ void LogFinished();
+
+ const char* id_;
+ uint32_t cmd_;
+ uint32_t op_id_;
+ uint32_t flags_;
+ const char* state_;
+
+ using clock = std::chrono::high_resolution_clock;
+ clock::time_point start_;
+ clock::time_point state_change_;
+ std::chrono::milliseconds Elapsed(clock::time_point end);
+
+ bool triggered_;
+};
+
+watcher::watcher(const char* id, const struct storage_msg* request)
+ : id_(id), state_(nullptr), triggered_(false) {
+ cmd_ = request->cmd;
+ op_id_ = request->op_id;
+ flags_ = request->flags;
+
+ start_ = clock::now();
+ state_change_ = start_;
+}
+
+void watcher::SetState(const char* new_state) {
+ state_ = new_state;
+ state_change_ = clock::now();
+}
+
+void watcher::LogTimeout() {
+ if (!triggered_) {
+ triggered_ = true;
+ LOG(ERROR) << "Storageproxyd watchdog triggered: " << id_ << " cmd: " << cmd_
+ << " op_id: " << op_id_ << " flags: " << flags_;
+ }
+ if (state_) {
+ LOG(ERROR) << "...elapsed: " << Elapsed(clock::now()).count() << "ms (" << state_ << " "
+ << Elapsed(state_change_).count() << "ms)";
+ } else {
+ LOG(ERROR) << "...elapsed: " << Elapsed(clock::now()).count() << "ms";
+ }
+}
+
+void watcher::LogFinished() {
+ if (triggered_) {
+ LOG(ERROR) << "...completed: " << Elapsed(clock::now()).count() << "ms";
+ }
+}
+
+std::chrono::milliseconds watcher::Elapsed(watcher::clock::time_point end) {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(end - start_);
+}
+
+namespace {
+
+class Watchdog {
+ private:
+ static constexpr std::chrono::milliseconds kDefaultTimeoutMs = std::chrono::milliseconds(500);
+ static constexpr std::chrono::milliseconds kMaxTimeoutMs = std::chrono::seconds(10);
+
+ public:
+ Watchdog() : watcher_(), done_(false) {}
+ ~Watchdog();
+ struct watcher* RegisterWatch(const char* id, const struct storage_msg* request);
+ void AddProgress(struct watcher* watcher, const char* state);
+ void UnRegisterWatch(struct watcher* watcher);
+
+ private:
+ // Syncronizes access to watcher_ and watcher_change_ between the main
+ // thread and watchdog loop thread. watcher_ may only be modified by the
+ // main thread; the watchdog loop is read-only.
+ std::mutex watcher_mutex_;
+ std::unique_ptr<struct watcher> watcher_;
+ std::condition_variable watcher_change_;
+
+ std::thread watchdog_thread_;
+ bool done_;
+
+ void WatchdogLoop();
+ void LogWatchdogTriggerLocked();
+};
+
+Watchdog gWatchdog;
+
+} // Anonymous namespace
+
+// Assumes that caller is single-threaded. If we want to use this from a
+// multi-threaded context we need to ensure that the watchdog thread is
+// initialized safely once and accessing an existing watcher is done while the
+// watcher lock is held.
+struct watcher* Watchdog::RegisterWatch(const char* id, const struct storage_msg* request) {
+ if (!watchdog_thread_.joinable()) {
+ watchdog_thread_ = std::thread(&Watchdog::WatchdogLoop, this);
+ }
+ if (watcher_) {
+ LOG(ERROR) << "Replacing registered watcher " << watcher_->id_;
+ UnRegisterWatch(watcher_.get());
+ }
+
+ struct watcher* ret = nullptr;
+ {
+ std::unique_lock<std::mutex> watcherLock(watcher_mutex_);
+ watcher_ = std::make_unique<struct watcher>(id, request);
+ ret = watcher_.get();
+ }
+ watcher_change_.notify_one();
+ return ret;
+}
+
+void Watchdog::UnRegisterWatch(struct watcher* watcher) {
+ {
+ std::lock_guard<std::mutex> watcherLock(watcher_mutex_);
+ if (!watcher_) {
+ LOG(ERROR) << "Cannot unregister watcher, no watcher registered";
+ return;
+ }
+ if (watcher_.get() != watcher) {
+ LOG(ERROR) << "Unregistering watcher that doesn't match current watcher";
+ }
+ watcher_->LogFinished();
+ watcher_.reset(nullptr);
+ }
+ watcher_change_.notify_one();
+}
+
+void Watchdog::AddProgress(struct watcher* watcher, const char* state) {
+ std::lock_guard<std::mutex> watcherLock(watcher_mutex_);
+ if (watcher_.get() != watcher) {
+ LOG(ERROR) << "Watcher was not registered, cannot log progress: " << state;
+ return;
+ }
+ watcher->SetState(state);
+}
+
+void Watchdog::WatchdogLoop() {
+ std::unique_lock<std::mutex> lock(watcher_mutex_);
+ std::chrono::milliseconds timeout = kDefaultTimeoutMs;
+
+ while (!done_) {
+ // wait for a watch to be registered
+ watcher_change_.wait(lock, [this] { return !!watcher_; });
+
+ // wait for the timeout or unregistration
+ timeout = kDefaultTimeoutMs;
+ do {
+ if (!watcher_change_.wait_for(lock, timeout, [this] { return !watcher_; })) {
+ watcher_->LogTimeout();
+ timeout = std::min(timeout * 2, kMaxTimeoutMs);
+ }
+ } while (!!watcher_);
+ }
+}
+
+Watchdog::~Watchdog() {
+ {
+ std::lock_guard<std::mutex> watcherLock(watcher_mutex_);
+ watcher_.reset(nullptr);
+ done_ = true;
+ }
+ watcher_change_.notify_one();
+ if (watchdog_thread_.joinable()) {
+ watchdog_thread_.join();
+ }
+}
+
+struct watcher* watch_start(const char* id, const struct storage_msg* request) {
+ return gWatchdog.RegisterWatch(id, request);
+}
+
+void watch_progress(struct watcher* watcher, const char* state) {
+ gWatchdog.AddProgress(watcher, state);
+}
+
+void watch_finish(struct watcher* watcher) {
+ gWatchdog.UnRegisterWatch(watcher);
+}
diff --git a/trusty/storage/proxy/watchdog.h b/trusty/storage/proxy/watchdog.h
new file mode 100644
index 0000000..9162fcb
--- /dev/null
+++ b/trusty/storage/proxy/watchdog.h
@@ -0,0 +1,59 @@
+/*
+ * 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 "storage.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct watcher;
+
+/**
+ * watch_start() - Create a watcher for a storage request
+ * @id: Identifier string to distinguish watchers
+ * @request: Incoming request from Trusty storage service
+ *
+ * Create a watcher that will start logging if not finished before a timeout.
+ * Only one watcher may be active at a time, and this function may only be
+ * called from a single thread.
+ */
+struct watcher* watch_start(const char* id, const struct storage_msg* request);
+
+/**
+ * watch_progress() - Note progress on servicing the current request
+ * @watcher: Current watcher, created by watch()
+ *
+ * Sets the current progress state of the watcher, to allow for more granular
+ * reporting of what exactly is stuck if the timeout is reached.
+ */
+void watch_progress(struct watcher* watcher, const char* state);
+
+/**
+ * watch_finish() - Finish watching and unregister the watch
+ * @watcher: Current watcher, created by watch(). Takes ownership of this pointer.
+ *
+ * Finish the current watch task. This function takes ownership of the watcher
+ * and destroys it, so @watcher must not be used again after calling this
+ * function.
+ */
+void watch_finish(struct watcher* watcher);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 0609709..1986c73 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -22,11 +22,23 @@
# For gatekeeper, we include the generic -service and -impl to use legacy
# HAL loading of gatekeeper.trusty.
+# Allow the KeyMint HAL service implementation to be selected at build time. This needs to be
+# done in sync with the TA implementation included in Trusty. Possible values are:
+#
+# - Rust implementation: export TRUSTY_KEYMINT_IMPL=rust
+# - C++ implementation: (any other value of TRUSTY_KEYMINT_IMPL)
+
+ifeq ($(TRUSTY_KEYMINT_IMPL),rust)
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty
+else
+ # Default to the C++ implementation
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.trusty
+endif
+
PRODUCT_PACKAGES += \
- android.hardware.security.keymint-service.trusty \
- android.hardware.gatekeeper@1.0-service.trusty \
+ $(LOCAL_KEYMINT_PRODUCT_PACKAGE) \
+ android.hardware.gatekeeper-service.trusty \
trusty_apploader \
- RemoteProvisioner
PRODUCT_PROPERTY_OVERRIDES += \
ro.hardware.keystore_desede=true \
diff --git a/trusty/utils/trusty-ut-ctrl/ut-ctrl.c b/trusty/utils/trusty-ut-ctrl/ut-ctrl.c
index 9e72af3..6cc6670 100644
--- a/trusty/utils/trusty-ut-ctrl/ut-ctrl.c
+++ b/trusty/utils/trusty-ut-ctrl/ut-ctrl.c
@@ -94,6 +94,7 @@
TEST_PASSED = 0,
TEST_FAILED = 1,
TEST_MESSAGE = 2,
+ TEST_TEXT = 3,
};
static int run_trusty_unitest(const char* utapp) {
@@ -121,7 +122,7 @@
break;
} else if (rx_buf[0] == TEST_FAILED) {
break;
- } else if (rx_buf[0] == TEST_MESSAGE) {
+ } else if (rx_buf[0] == TEST_MESSAGE || rx_buf[0] == TEST_TEXT) {
write(STDOUT_FILENO, rx_buf + 1, rc - 1);
} else {
fprintf(stderr, "%s: Bad message header: %d\n", __func__, rx_buf[0]);
diff --git a/usbd/Android.bp b/usbd/Android.bp
index 27db0fa..e67759c 100644
--- a/usbd/Android.bp
+++ b/usbd/Android.bp
@@ -8,10 +8,12 @@
srcs: ["usbd.cpp"],
shared_libs: [
"libbase",
+ "libbinder_ndk",
"libhidlbase",
"liblog",
"libutils",
"libhardware",
"android.hardware.usb.gadget@1.0",
+ "android.hardware.usb.gadget-V1-ndk",
],
}
diff --git a/usbd/usbd.cpp b/usbd/usbd.cpp
index 6e24d8e..0616cfb 100644
--- a/usbd/usbd.cpp
+++ b/usbd/usbd.cpp
@@ -18,43 +18,78 @@
#include <string>
+#include <aidl/android/hardware/usb/gadget/GadgetFunction.h>
+#include <aidl/android/hardware/usb/gadget/IUsbGadget.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <android/hardware/usb/gadget/1.0/IUsbGadget.h>
-#include <hidl/HidlTransportSupport.h>
-
+using aidl::android::hardware::usb::gadget::GadgetFunction;
using android::base::GetProperty;
using android::base::SetProperty;
-using android::hardware::configureRpcThreadpool;
-using android::hardware::usb::gadget::V1_0::GadgetFunction;
-using android::hardware::usb::gadget::V1_0::IUsbGadget;
using android::hardware::Return;
+using ndk::ScopedAStatus;
+using std::shared_ptr;
+
+std::atomic<int> sUsbOperationCount{};
int main(int /*argc*/, char** /*argv*/) {
if (GetProperty("ro.bootmode", "") == "charger") exit(0);
+ int operationId = sUsbOperationCount++;
- configureRpcThreadpool(1, true /*callerWillJoin*/);
- android::sp<IUsbGadget> gadget = IUsbGadget::getService();
- Return<void> ret;
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ const std::string service_name =
+ std::string(aidl::android::hardware::usb::gadget::IUsbGadget::descriptor)
+ .append("/default");
- if (gadget != nullptr) {
- LOG(INFO) << "Usb HAL found.";
- std::string function = GetProperty("persist.sys.usb.config", "");
- if (function == "adb") {
- LOG(INFO) << "peristent prop is adb";
- SetProperty("ctl.start", "adbd");
- ret = gadget->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::ADB),
- nullptr, 0);
+ std::string function = GetProperty("persist.sys.usb.config", "");
+ if (function == "adb") {
+ LOG(INFO) << "persistent prop is adb";
+ SetProperty("ctl.start", "adbd");
+ }
+
+ if (AServiceManager_isDeclared(service_name.c_str())) {
+ shared_ptr<aidl::android::hardware::usb::gadget::IUsbGadget> gadget_aidl =
+ aidl::android::hardware::usb::gadget::IUsbGadget::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(service_name.c_str())));
+ ScopedAStatus ret;
+ if (gadget_aidl != nullptr) {
+ LOG(INFO) << "Usb AIDL HAL found.";
+ if (function == "adb") {
+ ret = gadget_aidl->setCurrentUsbFunctions(
+ static_cast<uint64_t>(GadgetFunction::ADB), nullptr, 0, operationId);
+ } else {
+ LOG(INFO) << "Signal MTP to enable default functions";
+ ret = gadget_aidl->setCurrentUsbFunctions(
+ static_cast<uint64_t>(GadgetFunction::MTP), nullptr, 0, operationId);
+ }
+
+ if (!ret.isOk()) LOG(ERROR) << "Error while invoking usb hal";
} else {
- LOG(INFO) << "Signal MTP to enable default functions";
- ret = gadget->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::MTP),
- nullptr, 0);
+ LOG(INFO) << "Usb AIDL HAL not found";
}
-
- if (!ret.isOk()) LOG(ERROR) << "Error while invoking usb hal";
} else {
- LOG(INFO) << "Usb HAL not found";
+ android::sp<android::hardware::usb::gadget::V1_0::IUsbGadget> gadget =
+ android::hardware::usb::gadget::V1_0::IUsbGadget::getService();
+ Return<void> ret;
+ if (gadget != nullptr) {
+ LOG(INFO) << "Usb HAL found.";
+ if (function == "adb") {
+ ret = gadget->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::ADB),
+ nullptr, 0);
+ } else {
+ LOG(INFO) << "Signal MTP to enable default functions";
+ ret = gadget->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::MTP),
+ nullptr, 0);
+ }
+
+ if (!ret.isOk()) LOG(ERROR) << "Error while invoking usb hal";
+ } else {
+ LOG(INFO) << "Usb HAL not found";
+ }
}
exit(0);
}