Merge "Optimize cgroupfs dumping"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 34ccb21..8da1352 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -11,6 +11,286 @@
 
 # Grant unix world read/write permissions to kernel tracepoints.
 # Access control to these files is now entirely in selinux policy.
+    chmod 0755 /sys/kernel/debug/tracing/events
+    chmod 0755 /sys/kernel/debug/tracing/events/binder
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_lock
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_locked
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_set_priority
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction_alloc_buf
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction_received
+    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_unlock
+    chmod 0755 /sys/kernel/debug/tracing/events/block
+    chmod 0755 /sys/kernel/debug/tracing/events/block/block_rq_complete
+    chmod 0755 /sys/kernel/debug/tracing/events/block/block_rq_issue
+    chmod 0755 /sys/kernel/debug/tracing/events/cgroup
+    chmod 0755 /sys/kernel/debug/tracing/events/clk
+    chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_disable
+    chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_enable
+    chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_set_rate
+    chmod 0755 /sys/kernel/debug/tracing/events/cpufreq_interactive
+    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp
+    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_enter
+    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_pause
+    chmod 0755 /sys/kernel/debug/tracing/events/dma_fence
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_enter
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_load_inode
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter
+    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_get_data_block
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_iget
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin
+    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end
+    chmod 0755 /sys/kernel/debug/tracing/events/fence
+    chmod 0755 /sys/kernel/debug/tracing/events/filemap
+    chmod 0755 /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache
+    chmod 0755 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache
+    chmod 0755 /sys/kernel/debug/tracing/events/gpu_mem
+    chmod 0755 /sys/kernel/debug/tracing/events/gpu_mem/gpu_mem_total
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_read
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_reply
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_result
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_write
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_read
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_reply
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_result
+    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_write
+    chmod 0755 /sys/kernel/debug/tracing/events/ion
+    chmod 0755 /sys/kernel/debug/tracing/events/ion/ion_stat
+    chmod 0755 /sys/kernel/debug/tracing/events/ipi
+    chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_entry
+    chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_raise
+    chmod 0755 /sys/kernel/debug/tracing/events/irq
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/irq_handler_entry
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/irq_handler_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_entry
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_raise
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_entry
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_hi_entry
+    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_hi_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/kmem
+    chmod 0755 /sys/kernel/debug/tracing/events/kmem/ion_heap_grow
+    chmod 0755 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink
+    chmod 0755 /sys/kernel/debug/tracing/events/kmem/rss_stat
+    chmod 0755 /sys/kernel/debug/tracing/events/lowmemorykiller
+    chmod 0755 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill
+    chmod 0755 /sys/kernel/debug/tracing/events/mm_event
+    chmod 0755 /sys/kernel/debug/tracing/events/mm_event/mm_event_record
+    chmod 0755 /sys/kernel/debug/tracing/events/oom
+    chmod 0755 /sys/kernel/debug/tracing/events/oom/mark_victim
+    chmod 0755 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update
+    chmod 0755 /sys/kernel/debug/tracing/events/power
+    chmod 0755 /sys/kernel/debug/tracing/events/power/clock_disable
+    chmod 0755 /sys/kernel/debug/tracing/events/power/clock_enable
+    chmod 0755 /sys/kernel/debug/tracing/events/power/clock_set_rate
+    chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_frequency
+    chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits
+    chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_idle
+    chmod 0755 /sys/kernel/debug/tracing/events/power/gpu_frequency
+    chmod 0755 /sys/kernel/debug/tracing/events/power/suspend_resume
+    chmod 0755 /sys/kernel/debug/tracing/events/sched
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_pi_setprio
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_process_exit
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_process_free
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_switch
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_wakeup
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new
+    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_waking
+    chmod 0755 /sys/kernel/debug/tracing/events/signal
+    chmod 0755 /sys/kernel/debug/tracing/events/signal/signal_deliver
+    chmod 0755 /sys/kernel/debug/tracing/events/signal/signal_generate
+    chmod 0755 /sys/kernel/debug/tracing/events/sync
+    chmod 0755 /sys/kernel/debug/tracing/events/task
+    chmod 0755 /sys/kernel/debug/tracing/events/task/task_newtask
+    chmod 0755 /sys/kernel/debug/tracing/events/task/task_rename
+    chmod 0755 /sys/kernel/debug/tracing/events/thermal
+    chmod 0755 /sys/kernel/debug/tracing/events/thermal/cdev_update
+    chmod 0755 /sys/kernel/debug/tracing/events/thermal/thermal_temperature
+    chmod 0755 /sys/kernel/debug/tracing/events/vmscan
+    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin
+    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end
+    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep
+    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake
+    chmod 0755 /sys/kernel/debug/tracing/options
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu0
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu1
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu2
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu3
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu4
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu5
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu6
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu7
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu8
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu9
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu10
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu11
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu12
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu13
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu14
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu15
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu16
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu17
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu18
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu19
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu20
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu21
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu22
+    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu23
+    chmod 0755 /sys/kernel/tracing/events
+    chmod 0755 /sys/kernel/tracing/events/binder
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_lock
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_locked
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_set_priority
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction_alloc_buf
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction_received
+    chmod 0755 /sys/kernel/tracing/events/binder/binder_unlock
+    chmod 0755 /sys/kernel/tracing/events/block
+    chmod 0755 /sys/kernel/tracing/events/block/block_rq_complete
+    chmod 0755 /sys/kernel/tracing/events/block/block_rq_issue
+    chmod 0755 /sys/kernel/tracing/events/cgroup
+    chmod 0755 /sys/kernel/tracing/events/clk
+    chmod 0755 /sys/kernel/tracing/events/clk/clk_disable
+    chmod 0755 /sys/kernel/tracing/events/clk/clk_enable
+    chmod 0755 /sys/kernel/tracing/events/clk/clk_set_rate
+    chmod 0755 /sys/kernel/tracing/events/cpufreq_interactive
+    chmod 0755 /sys/kernel/tracing/events/cpuhp
+    chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_enter
+    chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_exit
+    chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_pause
+    chmod 0755 /sys/kernel/tracing/events/dma_fence
+    chmod 0755 /sys/kernel/tracing/events/ext4
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_da_write_begin
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_da_write_end
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_enter
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_exit
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_load_inode
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter
+    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit
+    chmod 0755 /sys/kernel/tracing/events/f2fs
+    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block
+    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_iget
+    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter
+    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit
+    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_write_begin
+    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_write_end
+    chmod 0755 /sys/kernel/tracing/events/fence
+    chmod 0755 /sys/kernel/tracing/events/filemap
+    chmod 0755 /sys/kernel/tracing/events/filemap/mm_filemap_add_to_page_cache
+    chmod 0755 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache
+    chmod 0755 /sys/kernel/tracing/events/gpu_mem
+    chmod 0755 /sys/kernel/tracing/events/gpu_mem/gpu_mem_total
+    chmod 0755 /sys/kernel/tracing/events/i2c
+    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_read
+    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_reply
+    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_result
+    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_write
+    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_read
+    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_reply
+    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_result
+    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_write
+    chmod 0755 /sys/kernel/tracing/events/ion
+    chmod 0755 /sys/kernel/tracing/events/ion/ion_stat
+    chmod 0755 /sys/kernel/tracing/events/ipi
+    chmod 0755 /sys/kernel/tracing/events/ipi/ipi_entry
+    chmod 0755 /sys/kernel/tracing/events/ipi/ipi_exit
+    chmod 0755 /sys/kernel/tracing/events/ipi/ipi_raise
+    chmod 0755 /sys/kernel/tracing/events/irq
+    chmod 0755 /sys/kernel/tracing/events/irq/irq_handler_entry
+    chmod 0755 /sys/kernel/tracing/events/irq/irq_handler_exit
+    chmod 0755 /sys/kernel/tracing/events/irq/softirq_entry
+    chmod 0755 /sys/kernel/tracing/events/irq/softirq_exit
+    chmod 0755 /sys/kernel/tracing/events/irq/softirq_raise
+    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_entry
+    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_exit
+    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_hi_entry
+    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_hi_exit
+    chmod 0755 /sys/kernel/tracing/events/kmem
+    chmod 0755 /sys/kernel/tracing/events/kmem/ion_heap_grow
+    chmod 0755 /sys/kernel/tracing/events/kmem/ion_heap_shrink
+    chmod 0755 /sys/kernel/tracing/events/kmem/rss_stat
+    chmod 0755 /sys/kernel/tracing/events/lowmemorykiller
+    chmod 0755 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill
+    chmod 0755 /sys/kernel/tracing/events/mm_event
+    chmod 0755 /sys/kernel/tracing/events/mm_event/mm_event_record
+    chmod 0755 /sys/kernel/tracing/events/oom
+    chmod 0755 /sys/kernel/tracing/events/oom/mark_victim
+    chmod 0755 /sys/kernel/tracing/events/oom/oom_score_adj_update
+    chmod 0755 /sys/kernel/tracing/events/power
+    chmod 0755 /sys/kernel/tracing/events/power/clock_disable
+    chmod 0755 /sys/kernel/tracing/events/power/clock_enable
+    chmod 0755 /sys/kernel/tracing/events/power/clock_set_rate
+    chmod 0755 /sys/kernel/tracing/events/power/cpu_frequency
+    chmod 0755 /sys/kernel/tracing/events/power/cpu_frequency_limits
+    chmod 0755 /sys/kernel/tracing/events/power/cpu_idle
+    chmod 0755 /sys/kernel/tracing/events/power/gpu_frequency
+    chmod 0755 /sys/kernel/tracing/events/power/suspend_resume
+    chmod 0755 /sys/kernel/tracing/events/sched
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_blocked_reason
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_cpu_hotplug
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_pi_setprio
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_process_exit
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_process_free
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_switch
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_wakeup
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_wakeup_new
+    chmod 0755 /sys/kernel/tracing/events/sched/sched_waking
+    chmod 0755 /sys/kernel/tracing/events/signal
+    chmod 0755 /sys/kernel/tracing/events/signal/signal_deliver
+    chmod 0755 /sys/kernel/tracing/events/signal/signal_generate
+    chmod 0755 /sys/kernel/tracing/events/sync
+    chmod 0755 /sys/kernel/tracing/events/task
+    chmod 0755 /sys/kernel/tracing/events/task/task_newtask
+    chmod 0755 /sys/kernel/tracing/events/task/task_rename
+    chmod 0755 /sys/kernel/tracing/events/thermal
+    chmod 0755 /sys/kernel/tracing/events/thermal/cdev_update
+    chmod 0755 /sys/kernel/tracing/events/thermal/thermal_temperature
+    chmod 0755 /sys/kernel/tracing/events/vmscan
+    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin
+    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_end
+    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_sleep
+    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_wake
+    chmod 0755 /sys/kernel/tracing/options
+    chmod 0755 /sys/kernel/tracing/per_cpu
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu0
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu1
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu2
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu3
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu4
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu5
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu6
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu7
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu8
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu9
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu10
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu11
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu12
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu13
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu14
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu15
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu16
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu17
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu18
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu19
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu20
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu21
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu22
+    chmod 0755 /sys/kernel/tracing/per_cpu/cpu23
     chmod 0666 /sys/kernel/debug/tracing/trace_clock
     chmod 0666 /sys/kernel/tracing/trace_clock
     chmod 0666 /sys/kernel/debug/tracing/buffer_size_kb
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 3b29e2b..c3256fc 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1131,16 +1131,15 @@
 }
 
 static int32_t copy_directory_recursive(const char* from, const char* to) {
-    char *argv[] = {
-        (char*) kCpPath,
-        (char*) "-F", /* delete any existing destination file first (--remove-destination) */
-        (char*) "-p", /* preserve timestamps, ownership, and permissions */
-        (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
-        (char*) "-P", /* Do not follow symlinks [default] */
-        (char*) "-d", /* don't dereference symlinks */
-        (char*) from,
-        (char*) to
-    };
+    char* argv[] =
+            {(char*)kCpPath,
+             (char*)"-F", /* delete any existing destination file first (--remove-destination) */
+             (char*)"--preserve=mode,ownership,timestamps,xattr", /* preserve properties */
+             (char*)"-R", /* recurse into subdirectories (DEST must be a directory) */
+             (char*)"-P", /* Do not follow symlinks [default] */
+             (char*)"-d", /* don't dereference symlinks */
+             (char*)from,
+             (char*)to};
 
     LOG(DEBUG) << "Copying " << from << " to " << to;
     return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 6aa32b8..e978e79 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -140,8 +140,8 @@
 
         PrepareEnvironmentVariables();
 
-        if (!EnsureBootImageAndDalvikCache()) {
-            LOG(ERROR) << "Bad boot image.";
+        if (!EnsureDalvikCache()) {
+            LOG(ERROR) << "Bad dalvik cache.";
             return 5;
         }
 
@@ -349,8 +349,8 @@
         }
     }
 
-    // Ensure that we have the right boot image and cache file structures.
-    bool EnsureBootImageAndDalvikCache() const {
+    // Ensure that we have the right cache file structures.
+    bool EnsureDalvikCache() const {
         if (parameters_.instruction_set == nullptr) {
             LOG(ERROR) << "Instruction set missing.";
             return false;
@@ -376,15 +376,6 @@
             }
         }
 
-        // Check whether we have a boot image.
-        // TODO: check that the files are correct wrt/ jars.
-        std::string preopted_boot_art_path =
-            StringPrintf("/apex/com.android.art/javalib/%s/boot.art", isa);
-        if (access(preopted_boot_art_path.c_str(), F_OK) != 0) {
-            PLOG(ERROR) << "Bad access() to " << preopted_boot_art_path;
-            return false;
-        }
-
         return true;
     }
 
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index b661684..51c4589 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -50,10 +50,6 @@
 static constexpr const char* kMinidebugDex2oatFlag = "--generate-mini-debug-info";
 static constexpr const char* kDisableCompactDexFlag = "--compact-dex-level=none";
 
-// Location of the JIT Zygote image.
-static const char* kJitZygoteImage =
-    "boot.art:/nonx/boot-framework.art!/system/etc/boot-image.prof";
-
 std::vector<std::string> SplitBySpaces(const std::string& str) {
     if (str.empty()) {
         return {};
@@ -84,9 +80,9 @@
                             int target_sdk_version,
                             bool enable_hidden_api_checks,
                             bool generate_compact_dex,
-                            bool use_jitzygote_image,
+                            bool use_jitzygote,
                             const char* compilation_reason) {
-    PrepareBootImageFlags(use_jitzygote_image);
+    PrepareBootImageFlags(use_jitzygote);
 
     PrepareInputFileFlags(output_oat, output_vdex, output_image, input_dex, input_vdex,
                           dex_metadata, profile, swap_fd, class_loader_context,
@@ -112,14 +108,14 @@
 
 RunDex2Oat::~RunDex2Oat() {}
 
-void RunDex2Oat::PrepareBootImageFlags(bool use_jitzygote_image) {
-    std::string boot_image;
-    if (use_jitzygote_image) {
-        boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
+void RunDex2Oat::PrepareBootImageFlags(bool use_jitzygote) {
+    if (use_jitzygote) {
+        // Don't pass a boot image because JIT Zygote should decide which image to use. Typically,
+        // it does not use any boot image on disk.
+        AddArg("--force-jit-zygote");
     } else {
-        boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
+        AddArg(MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s"));
     }
-    AddArg(boot_image);
 }
 
 void RunDex2Oat::PrepareInputFileFlags(const UniqueFile& output_oat,
diff --git a/cmds/installd/run_dex2oat.h b/cmds/installd/run_dex2oat.h
index 475e124..559244f 100644
--- a/cmds/installd/run_dex2oat.h
+++ b/cmds/installd/run_dex2oat.h
@@ -50,13 +50,13 @@
                     int target_sdk_version,
                     bool enable_hidden_api_checks,
                     bool generate_compact_dex,
-                    bool use_jitzygote_image,
+                    bool use_jitzygote,
                     const char* compilation_reason);
 
     void Exec(int exit_code);
 
   protected:
-    void PrepareBootImageFlags(bool use_jitzygote_image);
+    void PrepareBootImageFlags(bool use_jitzygote);
     void PrepareInputFileFlags(const UniqueFile& output_oat,
                                const UniqueFile& output_vdex,
                                const UniqueFile& output_image,
diff --git a/cmds/installd/run_dex2oat_test.cpp b/cmds/installd/run_dex2oat_test.cpp
index 0a638cd..2a8135a 100644
--- a/cmds/installd/run_dex2oat_test.cpp
+++ b/cmds/installd/run_dex2oat_test.cpp
@@ -114,7 +114,7 @@
         int target_sdk_version = 0;
         bool enable_hidden_api_checks = false;
         bool generate_compact_dex = true;
-        bool use_jitzygote_image = false;
+        bool use_jitzygote = false;
         const char* compilation_reason = nullptr;
     };
 
@@ -175,6 +175,7 @@
         default_expected_flags_["--swap-fd"] = FLAG_UNUSED;
         default_expected_flags_["--class-loader-context"] = FLAG_UNUSED;
         default_expected_flags_["--class-loader-context-fds"] = FLAG_UNUSED;
+        default_expected_flags_["--boot-image"] = FLAG_UNUSED;
 
         // Arch
         default_expected_flags_["--instruction-set"] = "=arm64";
@@ -190,6 +191,7 @@
         default_expected_flags_["--max-image-block-size"] = FLAG_UNUSED;
         default_expected_flags_["--very-large-app-threshold"] = FLAG_UNUSED;
         default_expected_flags_["--resolve-startup-const-strings"] = FLAG_UNUSED;
+        default_expected_flags_["--force-jit-zygote"] = FLAG_UNUSED;
 
         // Debug
         default_expected_flags_["--debuggable"] = FLAG_UNUSED;
@@ -256,7 +258,7 @@
                           args->target_sdk_version,
                           args->enable_hidden_api_checks,
                           args->generate_compact_dex,
-                          args->use_jitzygote_image,
+                          args->use_jitzygote,
                           args->compilation_reason);
         runner.Exec(/*exit_code=*/ 0);
     }
@@ -557,5 +559,22 @@
     VerifyExpectedFlags();
 }
 
+TEST_F(RunDex2OatTest, UseJitZygoteImage) {
+    auto args = RunDex2OatArgs::MakeDefaultTestArgs();
+    args->use_jitzygote = true;
+    CallRunDex2Oat(std::move(args));
+
+    SetExpectedFlagUsed("--force-jit-zygote", "");
+    VerifyExpectedFlags();
+}
+
+TEST_F(RunDex2OatTest, BootImage) {
+    setSystemProperty("dalvik.vm.boot-image", "foo.art:bar.art");
+    CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
+
+    SetExpectedFlagUsed("--boot-image", "=foo.art:bar.art");
+    VerifyExpectedFlags();
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index f60b32e..7448308 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -202,7 +202,6 @@
     sanitize: {
         misc_undefined: ["integer"],
     },
-    min_sdk_version: "30",
 
     tidy: true,
     tidy_flags: [
@@ -330,7 +329,6 @@
 cc_library {
     name: "libbinder_rpc_unstable",
     srcs: ["libbinder_rpc_unstable.cpp"],
-    defaults: ["libbinder_ndk_host_user"],
     shared_libs: [
         "libbase",
         "libbinder",
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 55d3d70..13f0a4c 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -352,11 +352,6 @@
     return gDisableBackgroundScheduling.load(std::memory_order_relaxed);
 }
 
-sp<ProcessState> IPCThreadState::process()
-{
-    return mProcess;
-}
-
 status_t IPCThreadState::clearLastError()
 {
     const status_t err = mLastError;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 6fb189c..f84f639 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2213,12 +2213,14 @@
               type == BINDER_TYPE_FD)) {
             // We should never receive other types (eg BINDER_TYPE_FDA) as long as we don't support
             // them in libbinder. If we do receive them, it probably means a kernel bug; try to
-            // recover gracefully by clearing out the objects, and releasing the objects we do
-            // know about.
+            // recover gracefully by clearing out the objects.
             android_errorWriteLog(0x534e4554, "135930648");
+            android_errorWriteLog(0x534e4554, "203847542");
             ALOGE("%s: unsupported type object (%" PRIu32 ") at offset %" PRIu64 "\n",
                   __func__, type, (uint64_t)offset);
-            releaseObjects();
+
+            // WARNING: callers of ipcSetDataReference need to make sure they
+            // don't rely on mObjectsSize in their release_func.
             mObjectsSize = 0;
             break;
         }
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 93ed50e..ace5cd5 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -287,8 +287,8 @@
 
     RpcConnectionHeader header;
     if (status == OK) {
-        status = client->interruptableReadFully(server->mShutdownTrigger.get(), &header,
-                                                sizeof(header), {});
+        iovec iov{&header, sizeof(header)};
+        status = client->interruptableReadFully(server->mShutdownTrigger.get(), &iov, 1, {});
         if (status != OK) {
             ALOGE("Failed to read ID for client connecting to RPC server: %s",
                   statusToString(status).c_str());
@@ -301,8 +301,9 @@
         if (header.sessionIdSize > 0) {
             if (header.sessionIdSize == kSessionIdBytes) {
                 sessionId.resize(header.sessionIdSize);
-                status = client->interruptableReadFully(server->mShutdownTrigger.get(),
-                                                        sessionId.data(), sessionId.size(), {});
+                iovec iov{sessionId.data(), sessionId.size()};
+                status =
+                        client->interruptableReadFully(server->mShutdownTrigger.get(), &iov, 1, {});
                 if (status != OK) {
                     ALOGE("Failed to read session ID for client connecting to RPC server: %s",
                           statusToString(status).c_str());
@@ -331,8 +332,8 @@
                     .version = protocolVersion,
             };
 
-            status = client->interruptableWriteFully(server->mShutdownTrigger.get(), &response,
-                                                     sizeof(response), {});
+            iovec iov{&response, sizeof(response)};
+            status = client->interruptableWriteFully(server->mShutdownTrigger.get(), &iov, 1, {});
             if (status != OK) {
                 ALOGE("Failed to send new session response: %s", statusToString(status).c_str());
                 // still need to cleanup before we can return
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index a5a2bb1..b84395e 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -615,8 +615,9 @@
         header.options |= RPC_CONNECTION_OPTION_INCOMING;
     }
 
+    iovec headerIov{&header, sizeof(header)};
     auto sendHeaderStatus =
-            server->interruptableWriteFully(mShutdownTrigger.get(), &header, sizeof(header), {});
+            server->interruptableWriteFully(mShutdownTrigger.get(), &headerIov, 1, {});
     if (sendHeaderStatus != OK) {
         ALOGE("Could not write connection header to socket: %s",
               statusToString(sendHeaderStatus).c_str());
@@ -624,9 +625,10 @@
     }
 
     if (sessionId.size() > 0) {
+        iovec sessionIov{const_cast<void*>(static_cast<const void*>(sessionId.data())),
+                         sessionId.size()};
         auto sendSessionIdStatus =
-                server->interruptableWriteFully(mShutdownTrigger.get(), sessionId.data(),
-                                                sessionId.size(), {});
+                server->interruptableWriteFully(mShutdownTrigger.get(), &sessionIov, 1, {});
         if (sendSessionIdStatus != OK) {
             ALOGE("Could not write session ID ('%s') to socket: %s",
                   base::HexString(sessionId.data(), sessionId.size()).c_str(),
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 09b3d68..6286c9c 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -19,6 +19,7 @@
 #include "RpcState.h"
 
 #include <android-base/hex.h>
+#include <android-base/macros.h>
 #include <android-base/scopeguard.h>
 #include <binder/BpBinder.h>
 #include <binder/IPCThreadState.h>
@@ -309,22 +310,18 @@
 }
 
 status_t RpcState::rpcSend(const sp<RpcSession::RpcConnection>& connection,
-                           const sp<RpcSession>& session, const char* what, const void* data,
-                           size_t size, const std::function<status_t()>& altPoll) {
-    LOG_RPC_DETAIL("Sending %s on RpcTransport %p: %s", what, connection->rpcTransport.get(),
-                   android::base::HexString(data, size).c_str());
-
-    if (size > std::numeric_limits<ssize_t>::max()) {
-        ALOGE("Cannot send %s at size %zu (too big)", what, size);
-        (void)session->shutdownAndWait(false);
-        return BAD_VALUE;
+                           const sp<RpcSession>& session, const char* what, iovec* iovs,
+                           size_t niovs, const std::function<status_t()>& altPoll) {
+    for (size_t i = 0; i < niovs; i++) {
+        LOG_RPC_DETAIL("Sending %s on RpcTransport %p: %s", what, connection->rpcTransport.get(),
+                       android::base::HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
     }
 
     if (status_t status =
                 connection->rpcTransport->interruptableWriteFully(session->mShutdownTrigger.get(),
-                                                                  data, size, altPoll);
+                                                                  iovs, niovs, altPoll);
         status != OK) {
-        LOG_RPC_DETAIL("Failed to write %s (%zu bytes) on RpcTransport %p, error: %s", what, size,
+        LOG_RPC_DETAIL("Failed to write %s (%zu iovs) on RpcTransport %p, error: %s", what, niovs,
                        connection->rpcTransport.get(), statusToString(status).c_str());
         (void)session->shutdownAndWait(false);
         return status;
@@ -334,34 +331,30 @@
 }
 
 status_t RpcState::rpcRec(const sp<RpcSession::RpcConnection>& connection,
-                          const sp<RpcSession>& session, const char* what, void* data,
-                          size_t size) {
-    if (size > std::numeric_limits<ssize_t>::max()) {
-        ALOGE("Cannot rec %s at size %zu (too big)", what, size);
-        (void)session->shutdownAndWait(false);
-        return BAD_VALUE;
-    }
-
+                          const sp<RpcSession>& session, const char* what, iovec* iovs,
+                          size_t niovs) {
     if (status_t status =
                 connection->rpcTransport->interruptableReadFully(session->mShutdownTrigger.get(),
-                                                                 data, size, {});
+                                                                 iovs, niovs, {});
         status != OK) {
-        LOG_RPC_DETAIL("Failed to read %s (%zu bytes) on RpcTransport %p, error: %s", what, size,
+        LOG_RPC_DETAIL("Failed to read %s (%zu iovs) on RpcTransport %p, error: %s", what, niovs,
                        connection->rpcTransport.get(), statusToString(status).c_str());
         (void)session->shutdownAndWait(false);
         return status;
     }
 
-    LOG_RPC_DETAIL("Received %s on RpcTransport %p: %s", what, connection->rpcTransport.get(),
-                   android::base::HexString(data, size).c_str());
+    for (size_t i = 0; i < niovs; i++) {
+        LOG_RPC_DETAIL("Received %s on RpcTransport %p: %s", what, connection->rpcTransport.get(),
+                       android::base::HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
+    }
     return OK;
 }
 
 status_t RpcState::readNewSessionResponse(const sp<RpcSession::RpcConnection>& connection,
                                           const sp<RpcSession>& session, uint32_t* version) {
     RpcNewSessionResponse response;
-    if (status_t status =
-                rpcRec(connection, session, "new session response", &response, sizeof(response));
+    iovec iov{&response, sizeof(response)};
+    if (status_t status = rpcRec(connection, session, "new session response", &iov, 1);
         status != OK) {
         return status;
     }
@@ -374,14 +367,15 @@
     RpcOutgoingConnectionInit init{
             .msg = RPC_CONNECTION_INIT_OKAY,
     };
-    return rpcSend(connection, session, "connection init", &init, sizeof(init));
+    iovec iov{&init, sizeof(init)};
+    return rpcSend(connection, session, "connection init", &iov, 1);
 }
 
 status_t RpcState::readConnectionInit(const sp<RpcSession::RpcConnection>& connection,
                                       const sp<RpcSession>& session) {
     RpcOutgoingConnectionInit init;
-    if (status_t status = rpcRec(connection, session, "connection init", &init, sizeof(init));
-        status != OK)
+    iovec iov{&init, sizeof(init)};
+    if (status_t status = rpcRec(connection, session, "connection init", &iov, 1); status != OK)
         return status;
 
     static_assert(sizeof(init.msg) == sizeof(RPC_CONNECTION_INIT_OKAY));
@@ -514,17 +508,6 @@
             .flags = flags,
             .asyncNumber = asyncNumber,
     };
-    CommandData transactionData(sizeof(RpcWireHeader) + sizeof(RpcWireTransaction) +
-                                data.dataSize());
-    if (!transactionData.valid()) {
-        return NO_MEMORY;
-    }
-
-    memcpy(transactionData.data() + 0, &command, sizeof(RpcWireHeader));
-    memcpy(transactionData.data() + sizeof(RpcWireHeader), &transaction,
-           sizeof(RpcWireTransaction));
-    memcpy(transactionData.data() + sizeof(RpcWireHeader) + sizeof(RpcWireTransaction), data.data(),
-           data.dataSize());
 
     constexpr size_t kWaitMaxUs = 1000000;
     constexpr size_t kWaitLogUs = 10000;
@@ -550,8 +533,13 @@
         return drainCommands(connection, session, CommandType::CONTROL_ONLY);
     };
 
-    if (status_t status = rpcSend(connection, session, "transaction", transactionData.data(),
-                                  transactionData.size(), drainRefs);
+    iovec iovs[]{
+            {&command, sizeof(RpcWireHeader)},
+            {&transaction, sizeof(RpcWireTransaction)},
+            {const_cast<uint8_t*>(data.data()), data.dataSize()},
+    };
+    if (status_t status =
+                rpcSend(connection, session, "transaction", iovs, arraysize(iovs), drainRefs);
         status != OK) {
         // TODO(b/167966510): need to undo onBinderLeaving - we know the
         // refcount isn't successfully transferred.
@@ -584,8 +572,8 @@
                                 const sp<RpcSession>& session, Parcel* reply) {
     RpcWireHeader command;
     while (true) {
-        if (status_t status = rpcRec(connection, session, "command header (for reply)", &command,
-                                     sizeof(command));
+        iovec iov{&command, sizeof(command)};
+        if (status_t status = rpcRec(connection, session, "command header (for reply)", &iov, 1);
             status != OK)
             return status;
 
@@ -599,8 +587,8 @@
     CommandData data(command.bodySize);
     if (!data.valid()) return NO_MEMORY;
 
-    if (status_t status = rpcRec(connection, session, "reply body", data.data(), command.bodySize);
-        status != OK)
+    iovec iov{data.data(), command.bodySize};
+    if (status_t status = rpcRec(connection, session, "reply body", &iov, 1); status != OK)
         return status;
 
     if (command.bodySize < sizeof(RpcWireReply)) {
@@ -653,11 +641,8 @@
             .command = RPC_COMMAND_DEC_STRONG,
             .bodySize = sizeof(RpcDecStrong),
     };
-    if (status_t status = rpcSend(connection, session, "dec ref header", &cmd, sizeof(cmd));
-        status != OK)
-        return status;
-
-    return rpcSend(connection, session, "dec ref body", &body, sizeof(body));
+    iovec iovs[]{{&cmd, sizeof(cmd)}, {&body, sizeof(body)}};
+    return rpcSend(connection, session, "dec ref", iovs, arraysize(iovs));
 }
 
 status_t RpcState::getAndExecuteCommand(const sp<RpcSession::RpcConnection>& connection,
@@ -665,8 +650,8 @@
     LOG_RPC_DETAIL("getAndExecuteCommand on RpcTransport %p", connection->rpcTransport.get());
 
     RpcWireHeader command;
-    if (status_t status = rpcRec(connection, session, "command header (for server)", &command,
-                                 sizeof(command));
+    iovec iov{&command, sizeof(command)};
+    if (status_t status = rpcRec(connection, session, "command header (for server)", &iov, 1);
         status != OK)
         return status;
 
@@ -726,9 +711,8 @@
     if (!transactionData.valid()) {
         return NO_MEMORY;
     }
-    if (status_t status = rpcRec(connection, session, "transaction body", transactionData.data(),
-                                 transactionData.size());
-        status != OK)
+    iovec iov{transactionData.data(), transactionData.size()};
+    if (status_t status = rpcRec(connection, session, "transaction body", &iov, 1); status != OK)
         return status;
 
     return processTransactInternal(connection, session, std::move(transactionData));
@@ -965,16 +949,12 @@
             .status = replyStatus,
     };
 
-    CommandData replyData(sizeof(RpcWireHeader) + sizeof(RpcWireReply) + reply.dataSize());
-    if (!replyData.valid()) {
-        return NO_MEMORY;
-    }
-    memcpy(replyData.data() + 0, &cmdReply, sizeof(RpcWireHeader));
-    memcpy(replyData.data() + sizeof(RpcWireHeader), &rpcReply, sizeof(RpcWireReply));
-    memcpy(replyData.data() + sizeof(RpcWireHeader) + sizeof(RpcWireReply), reply.data(),
-           reply.dataSize());
-
-    return rpcSend(connection, session, "reply", replyData.data(), replyData.size());
+    iovec iovs[]{
+            {&cmdReply, sizeof(RpcWireHeader)},
+            {&rpcReply, sizeof(RpcWireReply)},
+            {const_cast<uint8_t*>(reply.data()), reply.dataSize()},
+    };
+    return rpcSend(connection, session, "reply", iovs, arraysize(iovs));
 }
 
 status_t RpcState::processDecStrong(const sp<RpcSession::RpcConnection>& connection,
@@ -985,9 +965,8 @@
     if (!commandData.valid()) {
         return NO_MEMORY;
     }
-    if (status_t status =
-                rpcRec(connection, session, "dec ref body", commandData.data(), commandData.size());
-        status != OK)
+    iovec iov{commandData.data(), commandData.size()};
+    if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK)
         return status;
 
     if (command.bodySize != sizeof(RpcDecStrong)) {
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index dba0a43..5cad394 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -24,6 +24,8 @@
 #include <optional>
 #include <queue>
 
+#include <sys/uio.h>
+
 namespace android {
 
 struct RpcWireHeader;
@@ -177,12 +179,12 @@
     };
 
     [[nodiscard]] status_t rpcSend(const sp<RpcSession::RpcConnection>& connection,
-                                   const sp<RpcSession>& session, const char* what,
-                                   const void* data, size_t size,
+                                   const sp<RpcSession>& session, const char* what, iovec* iovs,
+                                   size_t niovs,
                                    const std::function<status_t()>& altPoll = nullptr);
     [[nodiscard]] status_t rpcRec(const sp<RpcSession::RpcConnection>& connection,
-                                  const sp<RpcSession>& session, const char* what, void* data,
-                                  size_t size);
+                                  const sp<RpcSession>& session, const char* what, iovec* iovs,
+                                  size_t niovs);
 
     [[nodiscard]] status_t waitForReply(const sp<RpcSession::RpcConnection>& connection,
                                         const sp<RpcSession>& session, Parcel* reply);
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 7669518..2182e18 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -43,12 +43,10 @@
         return ret;
     }
 
-    template <typename Buffer, typename SendOrReceive>
-    status_t interruptableReadOrWrite(FdTrigger* fdTrigger, Buffer buffer, size_t size,
+    template <typename SendOrReceive>
+    status_t interruptableReadOrWrite(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                       SendOrReceive sendOrReceiveFun, const char* funName,
                                       int16_t event, const std::function<status_t()>& altPoll) {
-        const Buffer end = buffer + size;
-
         MAYBE_WAIT_IN_FLAKE_MODE;
 
         // Since we didn't poll, we need to manually check to see if it was triggered. Otherwise, we
@@ -57,26 +55,61 @@
             return DEAD_OBJECT;
         }
 
+        // If iovs has one or more empty vectors at the end and
+        // we somehow advance past all the preceding vectors and
+        // pass some or all of the empty ones to sendmsg/recvmsg,
+        // the call will return processSize == 0. In that case
+        // we should be returning OK but instead return DEAD_OBJECT.
+        // To avoid this problem, we make sure here that the last
+        // vector at iovs[niovs - 1] has a non-zero length.
+        while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
+            niovs--;
+        }
+        if (niovs == 0) {
+            // The vectors are all empty, so we have nothing to send.
+            return OK;
+        }
+
         bool havePolled = false;
         while (true) {
-            ssize_t processSize = TEMP_FAILURE_RETRY(
-                    sendOrReceiveFun(mSocket.get(), buffer, end - buffer, MSG_NOSIGNAL));
+            msghdr msg{
+                    .msg_iov = iovs,
+                    .msg_iovlen = niovs,
+            };
+            ssize_t processSize =
+                    TEMP_FAILURE_RETRY(sendOrReceiveFun(mSocket.get(), &msg, MSG_NOSIGNAL));
 
             if (processSize < 0) {
                 int savedErrno = errno;
 
                 // Still return the error on later passes, since it would expose
                 // a problem with polling
-                if (havePolled ||
-                    (!havePolled && savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) {
+                if (havePolled || (savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) {
                     LOG_RPC_DETAIL("RpcTransport %s(): %s", funName, strerror(savedErrno));
                     return -savedErrno;
                 }
             } else if (processSize == 0) {
                 return DEAD_OBJECT;
             } else {
-                buffer += processSize;
-                if (buffer == end) {
+                while (processSize > 0 && niovs > 0) {
+                    auto& iov = iovs[0];
+                    if (static_cast<size_t>(processSize) < iov.iov_len) {
+                        // Advance the base of the current iovec
+                        iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
+                        iov.iov_len -= processSize;
+                        break;
+                    }
+
+                    // The current iovec was fully written
+                    processSize -= iov.iov_len;
+                    iovs++;
+                    niovs--;
+                }
+                if (niovs == 0) {
+                    LOG_ALWAYS_FATAL_IF(processSize > 0,
+                                        "Reached the end of iovecs "
+                                        "with %zd bytes remaining",
+                                        processSize);
                     return OK;
                 }
             }
@@ -95,16 +128,16 @@
         }
     }
 
-    status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size,
+    status_t interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                      const std::function<status_t()>& altPoll) override {
-        return interruptableReadOrWrite(fdTrigger, reinterpret_cast<const uint8_t*>(data), size,
-                                        send, "send", POLLOUT, altPoll);
+        return interruptableReadOrWrite(fdTrigger, iovs, niovs, sendmsg, "sendmsg", POLLOUT,
+                                        altPoll);
     }
 
-    status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size,
+    status_t interruptableReadFully(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                     const std::function<status_t()>& altPoll) override {
-        return interruptableReadOrWrite(fdTrigger, reinterpret_cast<uint8_t*>(data), size, recv,
-                                        "recv", POLLIN, altPoll);
+        return interruptableReadOrWrite(fdTrigger, iovs, niovs, recvmsg, "recvmsg", POLLIN,
+                                        altPoll);
     }
 
 private:
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index 7f810b1..c05ea15 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -275,9 +275,9 @@
     RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
           : mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
     Result<size_t> peek(void* buf, size_t size) override;
-    status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size,
+    status_t interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                      const std::function<status_t()>& altPoll) override;
-    status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size,
+    status_t interruptableReadFully(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                     const std::function<status_t()>& altPoll) override;
 
 private:
@@ -303,68 +303,83 @@
     return ret;
 }
 
-status_t RpcTransportTls::interruptableWriteFully(FdTrigger* fdTrigger, const void* data,
-                                                  size_t size,
+status_t RpcTransportTls::interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                                   const std::function<status_t()>& altPoll) {
-    auto buffer = reinterpret_cast<const uint8_t*>(data);
-    const uint8_t* end = buffer + size;
-
     MAYBE_WAIT_IN_FLAKE_MODE;
 
     // Before doing any I/O, check trigger once. This ensures the trigger is checked at least
     // once. The trigger is also checked via triggerablePoll() after every SSL_write().
     if (fdTrigger->isTriggered()) return DEAD_OBJECT;
 
-    while (buffer < end) {
-        size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
-        auto [writeSize, errorQueue] = mSsl.call(SSL_write, buffer, todo);
-        if (writeSize > 0) {
-            buffer += writeSize;
-            errorQueue.clear();
+    size_t size = 0;
+    for (size_t i = 0; i < niovs; i++) {
+        const iovec& iov = iovs[i];
+        if (iov.iov_len == 0) {
             continue;
         }
-        // SSL_write() should never return 0 unless BIO_write were to return 0.
-        int sslError = mSsl.getError(writeSize);
-        // TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
-        //   triggerablePoll()-ed. Then additionalEvent is no longer necessary.
-        status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
-                                                         "SSL_write", POLLIN, altPoll);
-        if (pollStatus != OK) return pollStatus;
-        // Do not advance buffer. Try SSL_write() again.
+        size += iov.iov_len;
+
+        auto buffer = reinterpret_cast<const uint8_t*>(iov.iov_base);
+        const uint8_t* end = buffer + iov.iov_len;
+        while (buffer < end) {
+            size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+            auto [writeSize, errorQueue] = mSsl.call(SSL_write, buffer, todo);
+            if (writeSize > 0) {
+                buffer += writeSize;
+                errorQueue.clear();
+                continue;
+            }
+            // SSL_write() should never return 0 unless BIO_write were to return 0.
+            int sslError = mSsl.getError(writeSize);
+            // TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
+            //   triggerablePoll()-ed. Then additionalEvent is no longer necessary.
+            status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
+                                                             "SSL_write", POLLIN, altPoll);
+            if (pollStatus != OK) return pollStatus;
+            // Do not advance buffer. Try SSL_write() again.
+        }
     }
     LOG_TLS_DETAIL("TLS: Sent %zu bytes!", size);
     return OK;
 }
 
-status_t RpcTransportTls::interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size,
+status_t RpcTransportTls::interruptableReadFully(FdTrigger* fdTrigger, iovec* iovs, size_t niovs,
                                                  const std::function<status_t()>& altPoll) {
-    auto buffer = reinterpret_cast<uint8_t*>(data);
-    uint8_t* end = buffer + size;
-
     MAYBE_WAIT_IN_FLAKE_MODE;
 
     // Before doing any I/O, check trigger once. This ensures the trigger is checked at least
     // once. The trigger is also checked via triggerablePoll() after every SSL_write().
     if (fdTrigger->isTriggered()) return DEAD_OBJECT;
 
-    while (buffer < end) {
-        size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
-        auto [readSize, errorQueue] = mSsl.call(SSL_read, buffer, todo);
-        if (readSize > 0) {
-            buffer += readSize;
-            errorQueue.clear();
+    size_t size = 0;
+    for (size_t i = 0; i < niovs; i++) {
+        const iovec& iov = iovs[i];
+        if (iov.iov_len == 0) {
             continue;
         }
-        if (readSize == 0) {
-            // SSL_read() only returns 0 on EOF.
-            errorQueue.clear();
-            return DEAD_OBJECT;
+        size += iov.iov_len;
+
+        auto buffer = reinterpret_cast<uint8_t*>(iov.iov_base);
+        const uint8_t* end = buffer + iov.iov_len;
+        while (buffer < end) {
+            size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+            auto [readSize, errorQueue] = mSsl.call(SSL_read, buffer, todo);
+            if (readSize > 0) {
+                buffer += readSize;
+                errorQueue.clear();
+                continue;
+            }
+            if (readSize == 0) {
+                // SSL_read() only returns 0 on EOF.
+                errorQueue.clear();
+                return DEAD_OBJECT;
+            }
+            int sslError = mSsl.getError(readSize);
+            status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
+                                                             "SSL_read", 0, altPoll);
+            if (pollStatus != OK) return pollStatus;
+            // Do not advance buffer. Try SSL_read() again.
         }
-        int sslError = mSsl.getError(readSize);
-        status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
-                                                         "SSL_read", 0, altPoll);
-        if (pollStatus != OK) return pollStatus;
-        // Do not advance buffer. Try SSL_read() again.
     }
     LOG_TLS_DETAIL("TLS: Received %zu bytes!", size);
     return OK;
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
index bffab5e..949835b 100644
--- a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -27,7 +27,5 @@
   @utf8InCpp String diskImagePath;
   long versionCode;
   @utf8InCpp String versionName;
-  boolean hasBootClassPathJars;
-  boolean hasDex2OatBootClassPathJars;
-  boolean hasSystemServerClassPathJars;
+  boolean hasClassPathJars;
 }
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 82bebc9..bf02099 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -54,8 +54,6 @@
     static  status_t            getProcessFreezeInfo(pid_t pid, uint32_t *sync_received,
                                                     uint32_t *async_received);
 
-            sp<ProcessState>    process();
-
             status_t            clearLastError();
 
             /**
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index db8b5e9..348bfeb 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -28,6 +28,8 @@
 
 #include <binder/RpcCertificateFormat.h>
 
+#include <sys/uio.h>
+
 namespace android {
 
 class FdTrigger;
@@ -44,6 +46,9 @@
     /**
      * Read (or write), but allow to be interrupted by a trigger.
      *
+     * iovs - array of iovecs to perform the operation on. The elements
+     * of the array may be modified by this method.
+     *
      * altPoll - function to be called instead of polling, when needing to wait
      * to read/write data. If this returns an error, that error is returned from
      * this function.
@@ -53,10 +58,10 @@
      *   error - interrupted (failure or trigger)
      */
     [[nodiscard]] virtual status_t interruptableWriteFully(
-            FdTrigger *fdTrigger, const void *buf, size_t size,
+            FdTrigger *fdTrigger, iovec *iovs, size_t niovs,
             const std::function<status_t()> &altPoll) = 0;
     [[nodiscard]] virtual status_t interruptableReadFully(
-            FdTrigger *fdTrigger, void *buf, size_t size,
+            FdTrigger *fdTrigger, iovec *iovs, size_t niovs,
             const std::function<status_t()> &altPoll) = 0;
 
 protected:
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 4289574..77493b3 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -32,17 +32,10 @@
     ],
 }
 
+// TODO(b/211908498): remove this
 cc_defaults {
     name: "libbinder_ndk_host_user",
     target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(n)=",
-                "-D__assert(a,b,c)=do { syslog(LOG_ERR, a \": \" c); abort(); } while(false)",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
         darwin: {
             enabled: false,
         },
@@ -52,7 +45,6 @@
 cc_library {
     name: "libbinder_ndk",
 
-    defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
     recovery_available: true,
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 6f1fdfc..76c7aac 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -32,11 +32,26 @@
 
 __BEGIN_DECLS
 
-#ifndef __ANDROID_API__
-#error Android builds must be compiled against a specific API. If this is an \
- android platform host build, you must use libbinder_ndk_host_user.
+#ifndef __BIONIC__
+
+#ifndef __INTRODUCED_IN
+#define __INTRODUCED_IN(n)
 #endif
 
+#ifndef __assert
+#define __assert(a, b, c)          \
+    do {                           \
+        syslog(LOG_ERR, a ": " c); \
+        abort();                   \
+    } while (false)
+#endif
+
+#ifndef __ANDROID_API__
+#define __ANDROID_API__ 10000
+#endif
+
+#endif  // __BIONIC__
+
 /**
  * Low-level status types for use in binder. This is the least preferable way to
  * return an error for binder services (where binder_exception_t should be used,
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index e2fc18d..e4df98a 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -127,14 +127,6 @@
     // Currently necessary for host builds
     // TODO(b/31559095): bionic on host should define this
     target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(n)=",
-                "-D__assert(a,b,c)=",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
         darwin: {
             enabled: false,
         },
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index c893899..63a4b2c 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -112,7 +112,7 @@
     BINDER_LIB_TEST_NOP_TRANSACTION_WAIT,
     BINDER_LIB_TEST_GETPID,
     BINDER_LIB_TEST_ECHO_VECTOR,
-    BINDER_LIB_TEST_REJECT_BUF,
+    BINDER_LIB_TEST_REJECT_OBJECTS,
     BINDER_LIB_TEST_CAN_GET_SID,
 };
 
@@ -1166,13 +1166,53 @@
     memcpy(parcelData, &obj, sizeof(obj));
     data.setDataSize(sizeof(obj));
 
+    EXPECT_EQ(data.objectsCount(), 1);
+
     // Either the kernel should reject this transaction (if it's correct), but
     // if it's not, the server implementation should return an error if it
     // finds an object in the received Parcel.
-    EXPECT_THAT(server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply),
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_REJECT_OBJECTS, data, &reply),
                 Not(StatusEq(NO_ERROR)));
 }
 
+TEST_F(BinderLibTest, WeakRejected) {
+    Parcel data, reply;
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    auto binder = sp<BBinder>::make();
+    wp<BBinder> wpBinder(binder);
+    flat_binder_object obj{
+            .hdr = {.type = BINDER_TYPE_WEAK_BINDER},
+            .flags = 0,
+            .binder = reinterpret_cast<uintptr_t>(wpBinder.get_refs()),
+            .cookie = reinterpret_cast<uintptr_t>(wpBinder.unsafe_get()),
+    };
+    data.setDataCapacity(1024);
+    // Write a bogus object at offset 0 to get an entry in the offset table
+    data.writeFileDescriptor(0);
+    EXPECT_EQ(data.objectsCount(), 1);
+    uint8_t *parcelData = const_cast<uint8_t *>(data.data());
+    // And now, overwrite it with the weak binder
+    memcpy(parcelData, &obj, sizeof(obj));
+    data.setDataSize(sizeof(obj));
+
+    // a previous bug caused other objects to be released an extra time, so we
+    // test with an object that libbinder will actually try to release
+    EXPECT_EQ(OK, data.writeStrongBinder(sp<BBinder>::make()));
+
+    EXPECT_EQ(data.objectsCount(), 2);
+
+    // send it many times, since previous error was memory corruption, make it
+    // more likely that the server crashes
+    for (size_t i = 0; i < 100; i++) {
+        EXPECT_THAT(server->transact(BINDER_LIB_TEST_REJECT_OBJECTS, data, &reply),
+                    StatusEq(BAD_VALUE));
+    }
+
+    EXPECT_THAT(server->pingBinder(), StatusEq(NO_ERROR));
+}
+
 TEST_F(BinderLibTest, GotSid) {
     sp<IBinder> server = addServer();
 
@@ -1566,7 +1606,7 @@
                 reply->writeUint64Vector(vector);
                 return NO_ERROR;
             }
-            case BINDER_LIB_TEST_REJECT_BUF: {
+            case BINDER_LIB_TEST_REJECT_OBJECTS: {
                 return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR;
             }
             case BINDER_LIB_TEST_CAN_GET_SID: {
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 5a96b78..ca68b99 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1674,8 +1674,8 @@
         static AssertionResult defaultPostConnect(RpcTransport* serverTransport,
                                                   FdTrigger* fdTrigger) {
             std::string message(kMessage);
-            auto status = serverTransport->interruptableWriteFully(fdTrigger, message.data(),
-                                                                   message.size(), {});
+            iovec messageIov{message.data(), message.size()};
+            auto status = serverTransport->interruptableWriteFully(fdTrigger, &messageIov, 1, {});
             if (status != OK) return AssertionFailure() << statusToString(status);
             return AssertionSuccess();
         }
@@ -1706,9 +1706,9 @@
         AssertionResult readMessage(const std::string& expectedMessage = kMessage) {
             LOG_ALWAYS_FATAL_IF(mClientTransport == nullptr, "setUpTransport not called or failed");
             std::string readMessage(expectedMessage.size(), '\0');
-            status_t readStatus =
-                    mClientTransport->interruptableReadFully(mFdTrigger.get(), readMessage.data(),
-                                                             readMessage.size(), {});
+            iovec readMessageIov{readMessage.data(), readMessage.size()};
+            status_t readStatus = mClientTransport->interruptableReadFully(mFdTrigger.get(),
+                                                                           &readMessageIov, 1, {});
             if (readStatus != OK) {
                 return AssertionFailure() << statusToString(readStatus);
             }
@@ -1902,8 +1902,8 @@
     bool shouldContinueWriting = false;
     auto serverPostConnect = [&](RpcTransport* serverTransport, FdTrigger* fdTrigger) {
         std::string message(RpcTransportTestUtils::kMessage);
-        auto status = serverTransport->interruptableWriteFully(fdTrigger, message.data(),
-                                                               message.size(), {});
+        iovec messageIov{message.data(), message.size()};
+        auto status = serverTransport->interruptableWriteFully(fdTrigger, &messageIov, 1, {});
         if (status != OK) return AssertionFailure() << statusToString(status);
 
         {
@@ -1913,7 +1913,8 @@
             }
         }
 
-        status = serverTransport->interruptableWriteFully(fdTrigger, msg2.data(), msg2.size(), {});
+        iovec msg2Iov{msg2.data(), msg2.size()};
+        status = serverTransport->interruptableWriteFully(fdTrigger, &msg2Iov, 1, {});
         if (status != DEAD_OBJECT)
             return AssertionFailure() << "When FdTrigger is shut down, interruptableWriteFully "
                                          "should return DEAD_OBJECT, but it is "
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index acf3f8f..1446802 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -9,7 +9,6 @@
 
 cc_fuzz {
     name: "binder_parcel_fuzzer",
-    defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
 
     fuzz_config: {
@@ -50,6 +49,9 @@
                 "libbinder",
             ],
         },
+        darwin: {
+            enabled: false,
+        },
     },
     // This flag enables verbose output in the fuzz target, and is very useful
     // for debugging a failure. If you are trying to diagnose how a crash was
@@ -63,7 +65,7 @@
     target: {
         darwin: {
             enabled: false,
-        }
+        },
     },
     srcs: [
         "random_fd.cpp",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 94e1ae1..5b59c59 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -117,16 +117,11 @@
     if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
 }
 
-void BLASTBufferItemConsumer::setBlastBufferQueue(BLASTBufferQueue* blastbufferqueue) {
-    std::scoped_lock lock(mBufferQueueMutex);
-    mBLASTBufferQueue = blastbufferqueue;
-}
-
 void BLASTBufferItemConsumer::onSidebandStreamChanged() {
-    std::scoped_lock lock(mBufferQueueMutex);
-    if (mBLASTBufferQueue != nullptr) {
+    sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+    if (bbq != nullptr) {
         sp<NativeHandle> stream = getSidebandStream();
-        mBLASTBufferQueue->setSidebandStream(stream);
+        bbq->setSidebandStream(stream);
     }
 }
 
@@ -147,7 +142,7 @@
     mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
                                                       GraphicBuffer::USAGE_HW_COMPOSER |
                                                               GraphicBuffer::USAGE_HW_TEXTURE,
-                                                      1, false);
+                                                      1, false, this);
     static int32_t id = 0;
     mName = name + "#" + std::to_string(id);
     auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
@@ -158,7 +153,6 @@
     mBufferItemConsumer->setBufferFreedListener(this);
     mBufferItemConsumer->setDefaultBufferSize(mSize.width, mSize.height);
     mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
-    mBufferItemConsumer->setBlastBufferQueue(this);
 
     ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
     mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
@@ -177,7 +171,6 @@
 }
 
 BLASTBufferQueue::~BLASTBufferQueue() {
-    mBufferItemConsumer->setBlastBufferQueue(nullptr);
     if (mPendingTransactions.empty()) {
         return;
     }
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 6c5b2aa..bc35792 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -38,11 +38,11 @@
 class BLASTBufferItemConsumer : public BufferItemConsumer {
 public:
     BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
-                            int bufferCount, bool controlledByApp)
+                            int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
           : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
+            mBLASTBufferQueue(std::move(bbq)),
             mCurrentlyConnected(false),
-            mPreviouslyConnected(false),
-            mBLASTBufferQueue(nullptr) {}
+            mPreviouslyConnected(false) {}
 
     void onDisconnect() override;
     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
@@ -59,15 +59,15 @@
     void onSidebandStreamChanged() override REQUIRES(mMutex);
 
 private:
+    const wp<BLASTBufferQueue> mBLASTBufferQueue;
+
     uint64_t mCurrentFrameNumber = 0;
 
     Mutex mMutex;
-    std::mutex mBufferQueueMutex;
     ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mMutex);
     std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mMutex);
     bool mCurrentlyConnected GUARDED_BY(mMutex);
     bool mPreviouslyConnected GUARDED_BY(mMutex);
-    BLASTBufferQueue* mBLASTBufferQueue GUARDED_BY(mBufferQueueMutex);
 };
 
 class BLASTBufferQueue
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index eb31e92..40b1fd0 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -101,7 +101,7 @@
     // TODO (marissaw): this library is not used by surfaceflinger. This is here so
     // the library compiled in a way that is accessible to system partition when running
     // IMapper's VTS.
-    required: ["libgralloctypes"]
+    required: ["libgralloctypes"],
 }
 
 cc_defaults {
@@ -114,10 +114,7 @@
         thin: true,
     },
     whole_program_vtables: true, // Requires ThinLTO
-    pgo: {
-        sampling: true,
-        profile_file: "surfaceflinger/surfaceflinger.profdata",
-    },
+    afdo: true,
     // TODO(b/131771163): Fix broken fuzzer support with LTO.
     sanitize: {
         fuzzer: false,
@@ -247,7 +244,7 @@
         "libSurfaceFlingerProp",
     ],
 
-     logtags: ["EventLog/EventLogTags.logtags"],
+    logtags: ["EventLog/EventLogTags.logtags"],
 }
 
 subdirs = [