summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/atrace/atrace.rc280
-rw-r--r--libs/binder/ndk/Android.bp2
-rw-r--r--libs/binder/ndk/include_cpp/android/binder_parcel_utils.h649
-rw-r--r--libs/binder/rust/src/binder.rs57
-rw-r--r--libs/binder/rust/src/lib.rs4
-rw-r--r--libs/binder/rust/tests/integration.rs108
-rw-r--r--libs/binder/tests/parcel_fuzzer/binder_ndk.cpp16
-rw-r--r--libs/graphicsenv/GpuStatsInfo.cpp3
-rw-r--r--libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h6
-rw-r--r--services/gpuservice/gpustats/GpuStats.cpp48
-rw-r--r--services/gpuservice/gpustats/include/gpustats/GpuStats.h12
-rw-r--r--services/gpuservice/tests/unittests/GpuStatsTest.cpp46
-rw-r--r--services/sensorservice/SensorDevice.cpp2
-rw-r--r--services/surfaceflinger/surfaceflinger.rc2
14 files changed, 1194 insertions, 41 deletions
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 34ccb21c1e..8da1352cca 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -11,6 +11,286 @@ on late-init
# 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/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index ee46fcb884..42895740ea 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -38,7 +38,7 @@ cc_defaults {
host: {
cflags: [
"-D__INTRODUCED_IN(n)=",
- "-D__assert(a,b,c)=",
+ "-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",
],
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 67623a6556..0bf1e3dba9 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -31,6 +31,7 @@
#include <android/binder_internal_logging.h>
#include <android/binder_parcel.h>
+#include <array>
#include <optional>
#include <string>
#include <type_traits>
@@ -86,9 +87,87 @@ static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_te
(is_specialization_v<T, std::optional> ||
is_specialization_v<T, std::unique_ptr>);
+// Tells if T is a fixed-size array.
+template <typename T>
+struct is_fixed_array : std::false_type {};
+
+template <typename T, size_t N>
+struct is_fixed_array<std::array<T, N>> : std::true_type {};
+
+template <typename T>
+static inline constexpr bool is_fixed_array_v = is_fixed_array<T>::value;
+
+template <typename T>
+static inline constexpr bool dependent_false_v = false;
} // namespace
/**
+ * This checks the length against the array size and retrieves the buffer. No allocation required.
+ */
+template <typename T, size_t N>
+static inline bool AParcel_stdArrayAllocator(void* arrayData, int32_t length, T** outBuffer) {
+ if (length < 0) return false;
+
+ if (length != static_cast<int32_t>(N)) {
+ return false;
+ }
+
+ std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData);
+ *outBuffer = arr->data();
+ return true;
+}
+
+/**
+ * This checks the length against the array size and retrieves the buffer. No allocation required.
+ */
+template <typename T, size_t N>
+static inline bool AParcel_nullableStdArrayAllocator(void* arrayData, int32_t length,
+ T** outBuffer) {
+ std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData);
+ if (length < 0) {
+ *arr = std::nullopt;
+ return true;
+ }
+
+ if (length != static_cast<int32_t>(N)) {
+ return false;
+ }
+
+ arr->emplace();
+ *outBuffer = (*arr)->data();
+ return true;
+}
+
+/**
+ * This checks the length against the array size. No allocation required.
+ */
+template <size_t N>
+static inline bool AParcel_stdArrayExternalAllocator(void* arrayData, int32_t length) {
+ (void)arrayData;
+ return length == static_cast<int32_t>(N);
+}
+
+/**
+ * This checks the length against the array size. No allocation required.
+ */
+template <typename T, size_t N>
+static inline bool AParcel_nullableStdArrayExternalAllocator(void* arrayData, int32_t length) {
+ std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData);
+
+ if (length < 0) {
+ *arr = std::nullopt;
+ return true;
+ }
+
+ if (length != static_cast<int32_t>(N)) {
+ return false;
+ }
+
+ arr->emplace();
+ return true;
+}
+
+/**
* This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
*/
template <typename T>
@@ -397,6 +476,118 @@ static inline const char* AParcel_nullableStdVectorStringElementGetter(const voi
}
/**
+ * This retrieves the underlying value in a std::array which may not be contiguous at index from a
+ * corresponding arrData.
+ */
+template <typename T, size_t N>
+static inline T AParcel_stdArrayGetter(const void* arrData, size_t index) {
+ const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrData);
+ return (*arr)[index];
+}
+
+/**
+ * This sets the underlying value in a corresponding arrData which may not be contiguous at
+ * index.
+ */
+template <typename T, size_t N>
+static inline void AParcel_stdArraySetter(void* arrData, size_t index, T value) {
+ std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrData);
+ (*arr)[index] = value;
+}
+
+/**
+ * This retrieves the underlying value in a std::array which may not be contiguous at index from a
+ * corresponding arrData.
+ */
+template <typename T, size_t N>
+static inline T AParcel_nullableStdArrayGetter(const void* arrData, size_t index) {
+ const std::optional<std::array<T, N>>* arr =
+ static_cast<const std::optional<std::array<T, N>>*>(arrData);
+ return (*arr)[index];
+}
+
+/**
+ * This sets the underlying value in a corresponding arrData which may not be contiguous at
+ * index.
+ */
+template <typename T, size_t N>
+static inline void AParcel_nullableStdArraySetter(void* arrData, size_t index, T value) {
+ std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrData);
+ (*arr)->at(index) = value;
+}
+
+/**
+ * Allocates a std::string inside of std::array<std::string, N> at index 'index' to size 'length'.
+ */
+template <size_t N>
+static inline bool AParcel_stdArrayStringElementAllocator(void* arrData, size_t index,
+ int32_t length, char** buffer) {
+ std::array<std::string, N>* arr = static_cast<std::array<std::string, N>*>(arrData);
+ std::string& element = arr->at(index);
+ return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::string inside of a std::array<std::string, N> at index
+ * 'index'.
+ */
+template <size_t N>
+static const char* AParcel_stdArrayStringElementGetter(const void* arrData, size_t index,
+ int32_t* outLength) {
+ const std::array<std::string, N>* arr = static_cast<const std::array<std::string, N>*>(arrData);
+ const std::string& element = arr->at(index);
+
+ *outLength = static_cast<int32_t>(element.size());
+ return element.c_str();
+}
+
+/**
+ * Allocates a std::string inside of std::array<std::optional<std::string>, N> at index 'index' to
+ * size 'length'.
+ */
+template <size_t N>
+static inline bool AParcel_stdArrayNullableStringElementAllocator(void* arrData, size_t index,
+ int32_t length, char** buffer) {
+ std::array<std::optional<std::string>, N>* arr =
+ static_cast<std::array<std::optional<std::string>, N>*>(arrData);
+ std::optional<std::string>& element = arr->at(index);
+ return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::string inside of a
+ * std::array<std::optional<std::string>, N> at index 'index'.
+ */
+template <size_t N>
+static const char* AParcel_stdArrayNullableStringElementGetter(const void* arrData, size_t index,
+ int32_t* outLength) {
+ const std::array<std::optional<std::string>, N>* arr =
+ static_cast<const std::array<std::optional<std::string>, N>*>(arrData);
+ const std::optional<std::string>& element = arr->at(index);
+
+ if (!element) {
+ *outLength = -1;
+ return nullptr;
+ }
+
+ *outLength = static_cast<int32_t>(element->size());
+ return element->c_str();
+}
+
+/**
+ * Allocates a std::string inside of std::optional<std::array<std::optional<std::string>, N>> at
+ * index 'index' to size 'length'.
+ */
+template <size_t N>
+static inline bool AParcel_nullableStdArrayStringElementAllocator(void* arrData, size_t index,
+ int32_t length, char** buffer) {
+ std::optional<std::array<std::optional<std::string>, N>>* arr =
+ static_cast<std::optional<std::array<std::optional<std::string>, N>>*>(arrData);
+ std::optional<std::string>& element = (*arr)->at(index);
+ return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
* Convenience API for writing a std::string.
*/
static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
@@ -482,9 +673,7 @@ static inline binder_status_t AParcel_readVector(
template <typename P>
static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) {
if constexpr (is_interface_v<P>) {
- if (!p) {
- return STATUS_UNEXPECTED_NULL;
- }
+ // Legacy behavior: allow null
return first_template_type_t<P>::writeToParcel(parcel, p);
} else {
static_assert(is_parcelable_v<P>);
@@ -502,13 +691,8 @@ static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P&
template <typename P>
static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) {
if constexpr (is_interface_v<P>) {
- binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p);
- if (status == STATUS_OK) {
- if (!*p) {
- return STATUS_UNEXPECTED_NULL;
- }
- }
- return status;
+ // Legacy behavior: allow null
+ return first_template_type_t<P>::readFromParcel(parcel, p);
} else {
static_assert(is_parcelable_v<P>);
int32_t null;
@@ -560,7 +744,7 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc
*p = std::nullopt;
return STATUS_OK;
}
- *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{});
+ p->emplace(first_template_type_t<P>());
return (*p)->readFromParcel(parcel);
} else {
static_assert(is_specialization_v<P, std::unique_ptr>);
@@ -578,6 +762,64 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc
}
}
+// Forward decls
+template <typename T>
+static inline binder_status_t AParcel_writeData(AParcel* parcel, const T& value);
+template <typename T>
+static inline binder_status_t AParcel_writeNullableData(AParcel* parcel, const T& value);
+template <typename T>
+static inline binder_status_t AParcel_readData(const AParcel* parcel, T* value);
+template <typename T>
+static inline binder_status_t AParcel_readNullableData(const AParcel* parcel, T* value);
+
+/**
+ * Reads an object of type T inside a std::array<T, N> at index 'index' from 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_readStdArrayData(const AParcel* parcel, void* arrayData, size_t index) {
+ std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData);
+ return AParcel_readData(parcel, &arr->at(index));
+}
+
+/**
+ * Reads a nullable object of type T inside a std::array<T, N> at index 'index' from 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_readStdArrayNullableData(const AParcel* parcel, void* arrayData,
+ size_t index) {
+ std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData);
+ return AParcel_readNullableData(parcel, &arr->at(index));
+}
+
+/**
+ * Reads a nullable object of type T inside a std::array<T, N> at index 'index' from 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_readNullableStdArrayNullableData(const AParcel* parcel, void* arrayData,
+ size_t index) {
+ std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData);
+ return AParcel_readNullableData(parcel, &(*arr)->at(index));
+}
+
+/**
+ * Writes an object of type T inside a std::array<T, N> at index 'index' to 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_writeStdArrayData(AParcel* parcel, const void* arrayData, size_t index) {
+ const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrayData);
+ return AParcel_writeData(parcel, arr->at(index));
+}
+
+/**
+ * Writes a nullable object of type T inside a std::array<T, N> at index 'index' to 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_writeStdArrayNullableData(AParcel* parcel, const void* arrayData,
+ size_t index) {
+ const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrayData);
+ return AParcel_writeNullableData(parcel, arr->at(index));
+}
+
/**
* Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
*/
@@ -721,9 +963,25 @@ inline binder_status_t AParcel_readNullableStdVectorParcelableElement<SpAIBinder
*/
template <typename P>
static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) {
- const void* vectorData = static_cast<const void*>(&vec);
- return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
- AParcel_writeStdVectorParcelableElement<P>);
+ if constexpr (std::is_enum_v<P>) {
+ if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+ return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()),
+ static_cast<int32_t>(vec.size()));
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+ return AParcel_writeInt32Array(parcel, reinterpret_cast<const int32_t*>(vec.data()),
+ static_cast<int32_t>(vec.size()));
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+ return AParcel_writeInt64Array(parcel, reinterpret_cast<const int64_t*>(vec.data()),
+ static_cast<int32_t>(vec.size()));
+ } else {
+ static_assert(dependent_false_v<P>, "unrecognized type");
+ }
+ } else {
+ static_assert(!std::is_same_v<P, std::string>, "specialization should be used");
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
+ AParcel_writeStdVectorParcelableElement<P>);
+ }
}
/**
@@ -731,9 +989,24 @@ static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::ve
*/
template <typename P>
static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>,
- AParcel_readStdVectorParcelableElement<P>);
+ if constexpr (std::is_enum_v<P>) {
+ void* vectorData = static_cast<void*>(vec);
+ if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+ return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+ return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+ return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
+ } else {
+ static_assert(dependent_false_v<P>, "unrecognized type");
+ }
+ } else {
+ static_assert(!std::is_same_v<P, std::string>, "specialization should be used");
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readParcelableArray(parcel, vectorData,
+ AParcel_stdVectorExternalAllocator<P>,
+ AParcel_readStdVectorParcelableElement<P>);
+ }
}
/**
@@ -742,10 +1015,30 @@ static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vec
template <typename P>
static inline binder_status_t AParcel_writeVector(AParcel* parcel,
const std::optional<std::vector<P>>& vec) {
- if (!vec) return AParcel_writeInt32(parcel, -1);
- const void* vectorData = static_cast<const void*>(&vec);
- return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()),
- AParcel_writeNullableStdVectorParcelableElement<P>);
+ if constexpr (std::is_enum_v<P>) {
+ if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+ return AParcel_writeByteArray(
+ parcel, vec ? reinterpret_cast<const int8_t*>(vec->data()) : nullptr,
+ vec ? static_cast<int32_t>(vec->size()) : -1);
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+ return AParcel_writeInt32Array(
+ parcel, vec ? reinterpret_cast<const int32_t*>(vec->data()) : nullptr,
+ vec ? static_cast<int32_t>(vec->size()) : -1);
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+ return AParcel_writeInt64Array(
+ parcel, vec ? reinterpret_cast<const int64_t*>(vec->data()) : nullptr,
+ vec ? static_cast<int32_t>(vec->size()) : -1);
+ } else {
+ static_assert(dependent_false_v<P>, "unrecognized type");
+ }
+ } else {
+ static_assert(!std::is_same_v<P, std::optional<std::string>>,
+ "specialization should be used");
+ if (!vec) return AParcel_writeInt32(parcel, -1);
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()),
+ AParcel_writeNullableStdVectorParcelableElement<P>);
+ }
}
/**
@@ -754,10 +1047,28 @@ static inline binder_status_t AParcel_writeVector(AParcel* parcel,
template <typename P>
static inline binder_status_t AParcel_readVector(const AParcel* parcel,
std::optional<std::vector<P>>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readParcelableArray(parcel, vectorData,
- AParcel_nullableStdVectorExternalAllocator<P>,
- AParcel_readNullableStdVectorParcelableElement<P>);
+ if constexpr (std::is_enum_v<P>) {
+ void* vectorData = static_cast<void*>(vec);
+ if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+ return AParcel_readByteArray(parcel, vectorData,
+ AParcel_nullableStdVectorAllocator<int8_t>);
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+ return AParcel_readInt32Array(parcel, vectorData,
+ AParcel_nullableStdVectorAllocator<int32_t>);
+ } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+ return AParcel_readInt64Array(parcel, vectorData,
+ AParcel_nullableStdVectorAllocator<int64_t>);
+ } else {
+ static_assert(dependent_false_v<P>, "unrecognized type");
+ }
+ } else {
+ static_assert(!std::is_same_v<P, std::optional<std::string>>,
+ "specialization should be used");
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readParcelableArray(parcel, vectorData,
+ AParcel_nullableStdVectorExternalAllocator<P>,
+ AParcel_readNullableStdVectorParcelableElement<P>);
+ }
}
// @START
@@ -1139,6 +1450,294 @@ static inline binder_status_t AParcel_resizeVector(const AParcel* parcel,
return STATUS_OK;
}
+/**
+ * Writes a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_writeFixedArray(AParcel* parcel,
+ const std::array<T, N>& arr) {
+ if constexpr (std::is_same_v<T, bool>) {
+ const void* arrayData = static_cast<const void*>(&arr);
+ return AParcel_writeBoolArray(parcel, arrayData, static_cast<int32_t>(N),
+ &AParcel_stdArrayGetter<T, N>);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(arr.data()),
+ static_cast<int32_t>(arr.size()));
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ return AParcel_writeCharArray(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ return AParcel_writeInt32Array(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ return AParcel_writeInt64Array(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+ } else if constexpr (std::is_same_v<T, float>) {
+ return AParcel_writeFloatArray(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+ } else if constexpr (std::is_same_v<T, double>) {
+ return AParcel_writeDoubleArray(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+ } else if constexpr (std::is_same_v<T, std::string>) {
+ const void* arrayData = static_cast<const void*>(&arr);
+ return AParcel_writeStringArray(parcel, arrayData, static_cast<int32_t>(N),
+ &AParcel_stdArrayStringElementGetter<N>);
+ } else {
+ const void* arrayData = static_cast<const void*>(&arr);
+ return AParcel_writeParcelableArray(parcel, arrayData, static_cast<int32_t>(N),
+ &AParcel_writeStdArrayData<T, N>);
+ }
+}
+
+/**
+ * Writes a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_writeFixedArrayWithNullableData(AParcel* parcel,
+ const std::array<T, N>& arr) {
+ if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, uint8_t> ||
+ std::is_same_v<T, char16_t> || std::is_same_v<T, int32_t> ||
+ std::is_same_v<T, int64_t> || std::is_same_v<T, float> ||
+ std::is_same_v<T, double> || std::is_same_v<T, std::string>) {
+ return AParcel_writeFixedArray(parcel, arr);
+ } else if constexpr (std::is_same_v<T, std::optional<std::string>>) {
+ const void* arrayData = static_cast<const void*>(&arr);
+ return AParcel_writeStringArray(parcel, arrayData, static_cast<int32_t>(N),
+ &AParcel_stdArrayNullableStringElementGetter<N>);
+ } else {
+ const void* arrayData = static_cast<const void*>(&arr);
+ return AParcel_writeParcelableArray(parcel, arrayData, static_cast<int32_t>(N),
+ &AParcel_writeStdArrayNullableData<T, N>);
+ }
+}
+
+/**
+ * Writes a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_writeNullableFixedArrayWithNullableData(
+ AParcel* parcel, const std::optional<std::array<T, N>>& arr) {
+ if (!arr) return AParcel_writeInt32(parcel, -1);
+ return AParcel_writeFixedArrayWithNullableData(parcel, arr.value());
+}
+
+/**
+ * Reads a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_readFixedArray(const AParcel* parcel, std::array<T, N>* arr) {
+ void* arrayData = static_cast<void*>(arr);
+ if constexpr (std::is_same_v<T, bool>) {
+ return AParcel_readBoolArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+ &AParcel_stdArraySetter<T, N>);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ return AParcel_readByteArray(parcel, arrayData, &AParcel_stdArrayAllocator<int8_t, N>);
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ return AParcel_readCharArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ return AParcel_readInt32Array(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ return AParcel_readInt64Array(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, float>) {
+ return AParcel_readFloatArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, double>) {
+ return AParcel_readDoubleArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, std::string>) {
+ return AParcel_readStringArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+ &AParcel_stdArrayStringElementAllocator<N>);
+ } else {
+ return AParcel_readParcelableArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+ &AParcel_readStdArrayData<T, N>);
+ }
+}
+
+/**
+ * Reads a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_readFixedArrayWithNullableData(const AParcel* parcel,
+ std::array<T, N>* arr) {
+ void* arrayData = static_cast<void*>(arr);
+ if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, uint8_t> ||
+ std::is_same_v<T, char16_t> || std::is_same_v<T, int32_t> ||
+ std::is_same_v<T, int64_t> || std::is_same_v<T, float> ||
+ std::is_same_v<T, double> || std::is_same_v<T, std::string>) {
+ return AParcel_readFixedArray(parcel, arr);
+ } else if constexpr (std::is_same_v<T, std::optional<std::string>>) {
+ return AParcel_readStringArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+ &AParcel_stdArrayNullableStringElementAllocator<N>);
+ } else {
+ return AParcel_readParcelableArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+ &AParcel_readStdArrayNullableData<T, N>);
+ }
+}
+
+/**
+ * Reads a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_readNullableFixedArrayWithNullableData(
+ const AParcel* parcel, std::optional<std::array<T, N>>* arr) {
+ void* arrayData = static_cast<void*>(arr);
+ if constexpr (std::is_same_v<T, bool>) {
+ return AParcel_readBoolArray(parcel, arrayData,
+ &AParcel_nullableStdArrayExternalAllocator<T, N>,
+ &AParcel_nullableStdArraySetter<T, N>);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ return AParcel_readByteArray(parcel, arrayData,
+ &AParcel_nullableStdArrayAllocator<int8_t, N>);
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ return AParcel_readCharArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ return AParcel_readInt32Array(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ return AParcel_readInt64Array(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, float>) {
+ return AParcel_readFloatArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, double>) {
+ return AParcel_readDoubleArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+ } else if constexpr (std::is_same_v<T, std::string>) {
+ return AParcel_readStringArray(parcel, arrayData,
+ &AParcel_nullableStdArrayExternalAllocator<N>,
+ &AParcel_nullableStdArrayStringElementAllocator<N>);
+ } else {
+ return AParcel_readParcelableArray(parcel, arrayData,
+ &AParcel_nullableStdArrayExternalAllocator<T, N>,
+ &AParcel_readStdArrayNullableData<T, N>);
+ }
+}
+
+/**
+ * Convenience API for writing a value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeData(AParcel* parcel, const T& value) {
+ if constexpr (is_specialization_v<T, std::vector>) {
+ return AParcel_writeVector(parcel, value);
+ } else if constexpr (is_fixed_array_v<T>) {
+ return AParcel_writeFixedArray(parcel, value);
+ } else if constexpr (std::is_same_v<std::string, T>) {
+ return AParcel_writeString(parcel, value);
+ } else if constexpr (std::is_same_v<bool, T>) {
+ return AParcel_writeBool(parcel, value);
+ } else if constexpr (std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>) {
+ return AParcel_writeByte(parcel, value);
+ } else if constexpr (std::is_same_v<char16_t, T>) {
+ return AParcel_writeChar(parcel, value);
+ } else if constexpr (std::is_same_v<int32_t, T>) {
+ return AParcel_writeInt32(parcel, value);
+ } else if constexpr (std::is_same_v<int64_t, T>) {
+ return AParcel_writeInt64(parcel, value);
+ } else if constexpr (std::is_same_v<float, T>) {
+ return AParcel_writeFloat(parcel, value);
+ } else if constexpr (std::is_same_v<double, T>) {
+ return AParcel_writeDouble(parcel, value);
+ } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+ return AParcel_writeRequiredParcelFileDescriptor(parcel, value);
+ } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+ return AParcel_writeRequiredStrongBinder(parcel, value);
+ } else if constexpr (std::is_enum_v<T>) {
+ return AParcel_writeData(parcel, static_cast<std::underlying_type_t<T>>(value));
+ } else if constexpr (is_interface_v<T>) {
+ return AParcel_writeParcelable(parcel, value);
+ } else if constexpr (is_parcelable_v<T>) {
+ return AParcel_writeParcelable(parcel, value);
+ } else {
+ static_assert(dependent_false_v<T>, "unrecognized type");
+ return STATUS_OK;
+ }
+}
+
+/**
+ * Convenience API for writing a nullable value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeNullableData(AParcel* parcel, const T& value) {
+ if constexpr (is_specialization_v<T, std::optional> &&
+ is_specialization_v<first_template_type_t<T>, std::vector>) {
+ return AParcel_writeVector(parcel, value);
+ } else if constexpr (is_specialization_v<T, std::optional> &&
+ is_fixed_array_v<first_template_type_t<T>>) {
+ return AParcel_writeNullableFixedArrayWithNullableData(parcel, value);
+ } else if constexpr (is_fixed_array_v<T>) { // happens with a nullable multi-dimensional array.
+ return AParcel_writeFixedArrayWithNullableData(parcel, value);
+ } else if constexpr (is_specialization_v<T, std::optional> &&
+ std::is_same_v<first_template_type_t<T>, std::string>) {
+ return AParcel_writeString(parcel, value);
+ } else if constexpr (is_nullable_parcelable_v<T> || is_interface_v<T>) {
+ return AParcel_writeNullableParcelable(parcel, value);
+ } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+ return AParcel_writeNullableParcelFileDescriptor(parcel, value);
+ } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+ return AParcel_writeNullableStrongBinder(parcel, value);
+ } else {
+ return AParcel_writeData(parcel, value);
+ }
+}
+
+/**
+ * Convenience API for reading a value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_readData(const AParcel* parcel, T* value) {
+ if constexpr (is_specialization_v<T, std::vector>) {
+ return AParcel_readVector(parcel, value);
+ } else if constexpr (is_fixed_array_v<T>) {
+ return AParcel_readFixedArray(parcel, value);
+ } else if constexpr (std::is_same_v<std::string, T>) {
+ return AParcel_readString(parcel, value);
+ } else if constexpr (std::is_same_v<bool, T>) {
+ return AParcel_readBool(parcel, value);
+ } else if constexpr (std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>) {
+ return AParcel_readByte(parcel, value);
+ } else if constexpr (std::is_same_v<char16_t, T>) {
+ return AParcel_readChar(parcel, value);
+ } else if constexpr (std::is_same_v<int32_t, T>) {
+ return AParcel_readInt32(parcel, value);
+ } else if constexpr (std::is_same_v<int64_t, T>) {
+ return AParcel_readInt64(parcel, value);
+ } else if constexpr (std::is_same_v<float, T>) {
+ return AParcel_readFloat(parcel, value);
+ } else if constexpr (std::is_same_v<double, T>) {
+ return AParcel_readDouble(parcel, value);
+ } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+ return AParcel_readRequiredParcelFileDescriptor(parcel, value);
+ } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+ return AParcel_readRequiredStrongBinder(parcel, value);
+ } else if constexpr (std::is_enum_v<T>) {
+ return AParcel_readData(parcel, reinterpret_cast<std::underlying_type_t<T>*>(value));
+ } else if constexpr (is_interface_v<T>) {
+ return AParcel_readParcelable(parcel, value);
+ } else if constexpr (is_parcelable_v<T>) {
+ return AParcel_readParcelable(parcel, value);
+ } else {
+ static_assert(dependent_false_v<T>, "unrecognized type");
+ return STATUS_OK;
+ }
+}
+
+/**
+ * Convenience API for reading a nullable value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_readNullableData(const AParcel* parcel, T* value) {
+ if constexpr (is_specialization_v<T, std::optional> &&
+ is_specialization_v<first_template_type_t<T>, std::vector>) {
+ return AParcel_readVector(parcel, value);
+ } else if constexpr (is_specialization_v<T, std::optional> &&
+ is_fixed_array_v<first_template_type_t<T>>) {
+ return AParcel_readNullableFixedArrayWithNullableData(parcel, value);
+ } else if constexpr (is_fixed_array_v<T>) { // happens with a nullable multi-dimensional array.
+ return AParcel_readFixedArrayWithNullableData(parcel, value);
+ } else if constexpr (is_specialization_v<T, std::optional> &&
+ std::is_same_v<first_template_type_t<T>, std::string>) {
+ return AParcel_readString(parcel, value);
+ } else if constexpr (is_nullable_parcelable_v<T> || is_interface_v<T>) {
+ return AParcel_readNullableParcelable(parcel, value);
+ } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+ return AParcel_readNullableParcelFileDescriptor(parcel, value);
+ } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+ return AParcel_readNullableStrongBinder(parcel, value);
+ } else {
+ return AParcel_readData(parcel, value);
+ }
+}
+
} // namespace ndk
/** @} */
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 3d2eddf611..4d6b294000 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -66,6 +66,35 @@ pub trait Interface: Send + Sync {
}
}
+/// Implemented by sync interfaces to specify what the associated async interface is.
+/// Generic to handle the fact that async interfaces are generic over a thread pool.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToAsyncInterface<P>
+where
+ Self: Interface,
+ Self::Target: FromIBinder,
+{
+ /// The async interface associated with this sync interface.
+ type Target: ?Sized;
+}
+
+/// Implemented by async interfaces to specify what the associated sync interface is.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToSyncInterface
+where
+ Self: Interface,
+ Self::Target: FromIBinder,
+{
+ /// The sync interface associated with this async interface.
+ type Target: ?Sized;
+}
+
/// Interface stability promise
///
/// An interface can promise to be a stable vendor interface ([`Vintf`]), or
@@ -337,6 +366,26 @@ impl<I: FromIBinder + ?Sized> Strong<I> {
pub fn downgrade(this: &Strong<I>) -> Weak<I> {
Weak::new(this)
}
+
+ /// Convert this synchronous binder handle into an asynchronous one.
+ pub fn into_async<P>(self) -> Strong<<I as ToAsyncInterface<P>>::Target>
+ where
+ I: ToAsyncInterface<P>,
+ {
+ // By implementing the ToAsyncInterface trait, it is guaranteed that the binder
+ // object is also valid for the target type.
+ FromIBinder::try_from(self.0.as_binder()).unwrap()
+ }
+
+ /// Convert this asynchronous binder handle into a synchronous one.
+ pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
+ where
+ I: ToSyncInterface,
+ {
+ // By implementing the ToSyncInterface trait, it is guaranteed that the binder
+ // object is also valid for the target type.
+ FromIBinder::try_from(self.0.as_binder()).unwrap()
+ }
}
impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
@@ -1017,6 +1066,14 @@ macro_rules! declare_binder_interface {
.expect(concat!("Error cloning interface ", stringify!($async_interface)))
}
}
+
+ impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
+ type Target = dyn $async_interface<P>;
+ }
+
+ impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
+ type Target = dyn $interface;
+ }
)?
};
}
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index b94dfa137e..7c04a7207b 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -109,8 +109,8 @@ pub mod parcel;
pub use crate::binder::{
BinderFeatures, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable,
- Stability, Strong, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION,
- FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
+ Stability, Strong, ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, Weak,
+ FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
};
pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 40359b4749..80dc47682c 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -100,6 +100,7 @@ enum TestTransactionCode {
Test = FIRST_CALL_TRANSACTION,
GetDumpArgs,
GetSelinuxContext,
+ GetIsHandlingTransaction,
}
impl TryFrom<u32> for TestTransactionCode {
@@ -112,6 +113,7 @@ impl TryFrom<u32> for TestTransactionCode {
_ if c == TestTransactionCode::GetSelinuxContext as u32 => {
Ok(TestTransactionCode::GetSelinuxContext)
}
+ _ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => Ok(TestTransactionCode::GetIsHandlingTransaction),
_ => Err(StatusCode::UNKNOWN_TRANSACTION),
}
}
@@ -140,6 +142,10 @@ impl ITest for TestService {
ThreadState::with_calling_sid(|sid| sid.map(|s| s.to_string_lossy().into_owned()));
sid.ok_or(StatusCode::UNEXPECTED_NULL)
}
+
+ fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+ Ok(binder::is_handling_transaction())
+ }
}
/// Trivial testing binder interface
@@ -152,6 +158,9 @@ pub trait ITest: Interface {
/// Returns the caller's SELinux context
fn get_selinux_context(&self) -> binder::Result<String>;
+
+ /// Returns the value of calling `is_handling_transaction`.
+ fn get_is_handling_transaction(&self) -> binder::Result<bool>;
}
/// Async trivial testing binder interface
@@ -164,6 +173,9 @@ pub trait IATest<P>: Interface {
/// Returns the caller's SELinux context
fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
+
+ /// Returns the value of calling `is_handling_transaction`.
+ fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>>;
}
declare_binder_interface! {
@@ -186,6 +198,7 @@ fn on_transact(
TestTransactionCode::Test => reply.write(&service.test()?),
TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
+ TestTransactionCode::GetIsHandlingTransaction => reply.write(&service.get_is_handling_transaction()?),
}
}
@@ -212,6 +225,15 @@ impl ITest for BpTest {
)?;
reply.read()
}
+
+ fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+ let reply = self.binder.transact(
+ TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
+ 0,
+ |_| Ok(()),
+ )?;
+ reply.read()
+ }
}
impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
@@ -238,6 +260,14 @@ impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
|reply| async move { reply?.read() }
)
}
+
+ fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
+ let binder = self.binder.clone();
+ P::spawn(
+ move || binder.transact(TestTransactionCode::GetIsHandlingTransaction as TransactionCode, 0, |_| Ok(())),
+ |reply| async move { reply?.read() }
+ )
+ }
}
impl ITest for Binder<BnTest> {
@@ -252,6 +282,10 @@ impl ITest for Binder<BnTest> {
fn get_selinux_context(&self) -> binder::Result<String> {
self.0.get_selinux_context()
}
+
+ fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+ self.0.get_is_handling_transaction()
+ }
}
impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
@@ -269,6 +303,11 @@ impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
let res = self.0.get_selinux_context();
Box::pin(async move { res })
}
+
+ fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
+ let res = self.0.get_is_handling_transaction();
+ Box::pin(async move { res })
+ }
}
/// Trivial testing binder interface
@@ -500,7 +539,7 @@ mod tests {
#[tokio::test]
async fn get_selinux_context_async() {
- let service_name = "get_selinux_context";
+ let service_name = "get_selinux_context_async";
let _process = ScopedServiceProcess::new(service_name);
let test_client: Strong<dyn IATest<Tokio>> =
binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
@@ -510,6 +549,32 @@ mod tests {
);
}
+ #[tokio::test]
+ async fn get_selinux_context_sync_to_async() {
+ let service_name = "get_selinux_context";
+ let _process = ScopedServiceProcess::new(service_name);
+ let test_client: Strong<dyn ITest> =
+ binder::get_interface(service_name).expect("Did not get manager binder service");
+ let test_client = test_client.into_async::<Tokio>();
+ assert_eq!(
+ test_client.get_selinux_context().await.unwrap(),
+ get_expected_selinux_context()
+ );
+ }
+
+ #[tokio::test]
+ async fn get_selinux_context_async_to_sync() {
+ let service_name = "get_selinux_context";
+ let _process = ScopedServiceProcess::new(service_name);
+ let test_client: Strong<dyn IATest<Tokio>> =
+ binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+ let test_client = test_client.into_sync();
+ assert_eq!(
+ test_client.get_selinux_context().unwrap(),
+ get_expected_selinux_context()
+ );
+ }
+
struct Bools {
binder_died: Arc<AtomicBool>,
binder_dealloc: Arc<AtomicBool>,
@@ -867,4 +932,45 @@ mod tests {
Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
}
}
+
+ #[test]
+ fn get_is_handling_transaction() {
+ let service_name = "get_is_handling_transaction";
+ let _process = ScopedServiceProcess::new(service_name);
+ let test_client: Strong<dyn ITest> =
+ binder::get_interface(service_name).expect("Did not get manager binder service");
+ // Should be true externally.
+ assert!(test_client.get_is_handling_transaction().unwrap());
+
+ // Should be false locally.
+ assert!(!binder::is_handling_transaction());
+
+ // Should also be false in spawned thread.
+ std::thread::spawn(|| {
+ assert!(!binder::is_handling_transaction());
+ }).join().unwrap();
+ }
+
+ #[tokio::test]
+ async fn get_is_handling_transaction_async() {
+ let service_name = "get_is_handling_transaction_async";
+ let _process = ScopedServiceProcess::new(service_name);
+ let test_client: Strong<dyn IATest<Tokio>> =
+ binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+ // Should be true externally.
+ assert!(test_client.get_is_handling_transaction().await.unwrap());
+
+ // Should be false locally.
+ assert!(!binder::is_handling_transaction());
+
+ // Should also be false in spawned task.
+ tokio::spawn(async {
+ assert!(!binder::is_handling_transaction());
+ }).await.unwrap();
+
+ // And in spawn_blocking task.
+ tokio::task::spawn_blocking(|| {
+ assert!(!binder::is_handling_transaction());
+ }).await.unwrap();
+ }
}
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 752fcbb34c..5aeb5cc6f2 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -156,5 +156,21 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{
PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector),
PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector),
PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector),
+
+ // methods for std::array<T,N>
+#define COMMA ,
+ PARCEL_READ(std::array<bool COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<uint8_t COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<char16_t COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<int32_t COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<int64_t COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<float COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<double COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<std::string COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<SomeParcelable COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<ndk::SpAIBinder COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<ndk::ScopedFileDescriptor COMMA 3>, ndk::AParcel_readData),
+ PARCEL_READ(std::array<std::shared_ptr<ISomeInterface> COMMA 3>, ndk::AParcel_readData),
+#undef COMMA
};
// clang-format on
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
index f2d0943e86..858739c9dd 100644
--- a/libs/graphicsenv/GpuStatsInfo.cpp
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -88,6 +88,7 @@ status_t GpuStatsAppInfo::writeToParcel(Parcel* parcel) const {
if ((status = parcel->writeBool(cpuVulkanInUse)) != OK) return status;
if ((status = parcel->writeBool(falsePrerotation)) != OK) return status;
if ((status = parcel->writeBool(gles1InUse)) != OK) return status;
+ if ((status = parcel->writeBool(angleInUse)) != OK) return status;
return OK;
}
@@ -101,6 +102,7 @@ status_t GpuStatsAppInfo::readFromParcel(const Parcel* parcel) {
if ((status = parcel->readBool(&cpuVulkanInUse)) != OK) return status;
if ((status = parcel->readBool(&falsePrerotation)) != OK) return status;
if ((status = parcel->readBool(&gles1InUse)) != OK) return status;
+ if ((status = parcel->readBool(&angleInUse)) != OK) return status;
return OK;
}
@@ -111,6 +113,7 @@ std::string GpuStatsAppInfo::toString() const {
StringAppendF(&result, "cpuVulkanInUse = %d\n", cpuVulkanInUse);
StringAppendF(&result, "falsePrerotation = %d\n", falsePrerotation);
StringAppendF(&result, "gles1InUse = %d\n", gles1InUse);
+ StringAppendF(&result, "angleInUse = %d\n", angleInUse);
result.append("glDriverLoadingTime:");
for (int32_t loadingTime : glDriverLoadingTime) {
StringAppendF(&result, " %d", loadingTime);
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 9aba69fd07..5b513d2a79 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -16,6 +16,7 @@
#pragma once
+#include <chrono>
#include <string>
#include <vector>
@@ -52,7 +53,7 @@ public:
};
/*
- * class for transporting gpu app stats from GpuService to authorized recipents.
+ * class for transporting gpu app stats from GpuService to authorized recipients.
* This class is intended to be a data container.
*/
class GpuStatsAppInfo : public Parcelable {
@@ -72,6 +73,9 @@ public:
bool cpuVulkanInUse = false;
bool falsePrerotation = false;
bool gles1InUse = false;
+ bool angleInUse = false;
+
+ std::chrono::time_point<std::chrono::system_clock> lastAccessTime;
};
/*
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 220952d892..d033453dd7 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -84,6 +84,38 @@ static void addLoadingTime(GpuStatsInfo::Driver driver, int64_t driverLoadingTim
}
}
+void GpuStats::purgeOldDriverStats() {
+ ALOG_ASSERT(mAppStats.size() == MAX_NUM_APP_RECORDS);
+
+ struct GpuStatsApp {
+ // Key is <app package name>+<driver version code>.
+ const std::string *appStatsKey = nullptr;
+ const std::chrono::time_point<std::chrono::system_clock> *lastAccessTime = nullptr;
+ };
+ std::vector<GpuStatsApp> gpuStatsApps(MAX_NUM_APP_RECORDS);
+
+ // Create a list of pointers to package names and their last access times.
+ int index = 0;
+ for (const auto & [appStatsKey, gpuStatsAppInfo] : mAppStats) {
+ GpuStatsApp &gpuStatsApp = gpuStatsApps[index];
+ gpuStatsApp.appStatsKey = &appStatsKey;
+ gpuStatsApp.lastAccessTime = &gpuStatsAppInfo.lastAccessTime;
+ ++index;
+ }
+
+ // Sort the list with the oldest access times at the front.
+ std::sort(gpuStatsApps.begin(), gpuStatsApps.end(), [](GpuStatsApp a, GpuStatsApp b) -> bool {
+ return *a.lastAccessTime < *b.lastAccessTime;
+ });
+
+ // Remove the oldest packages from mAppStats to make room for new apps.
+ for (int i = 0; i < APP_RECORD_HEADROOM; ++i) {
+ mAppStats.erase(*gpuStatsApps[i].appStatsKey);
+ gpuStatsApps[i].appStatsKey = nullptr;
+ gpuStatsApps[i].lastAccessTime = nullptr;
+ }
+}
+
void GpuStats::insertDriverStats(const std::string& driverPackageName,
const std::string& driverVersionName, uint64_t driverVersionCode,
int64_t driverBuildTime, const std::string& appPackageName,
@@ -123,19 +155,22 @@ void GpuStats::insertDriverStats(const std::string& driverPackageName,
const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
if (!mAppStats.count(appStatsKey)) {
if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
- ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats.");
- return;
+ ALOGV("GpuStatsAppInfo has reached maximum size. Removing old stats to make room.");
+ purgeOldDriverStats();
}
GpuStatsAppInfo appInfo;
addLoadingTime(driver, driverLoadingTime, &appInfo);
appInfo.appPackageName = appPackageName;
appInfo.driverVersionCode = driverVersionCode;
+ appInfo.angleInUse = driverPackageName == "angle";
+ appInfo.lastAccessTime = std::chrono::system_clock::now();
mAppStats.insert({appStatsKey, appInfo});
- return;
+ } else {
+ mAppStats[appStatsKey].angleInUse = driverPackageName == "angle";
+ addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
+ mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now();
}
-
- addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
}
void GpuStats::insertTargetStats(const std::string& appPackageName,
@@ -311,7 +346,8 @@ AStatsManager_PullAtomCallbackReturn GpuStats::pullAppInfoAtom(AStatsEventList*
angleDriverBytes.length()),
ele.second.cpuVulkanInUse,
ele.second.falsePrerotation,
- ele.second.gles1InUse);
+ ele.second.gles1InUse,
+ ele.second.angleInUse);
}
}
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index 55f0da1bc5..2aba651af9 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -46,6 +46,11 @@ public:
// This limits the worst case number of loading times tracked.
static const size_t MAX_NUM_LOADING_TIMES = 50;
+ // Below limits the memory usage of GpuStats to be less than 10KB. This is
+ // the preferred number for statsd while maintaining nice data quality.
+ static const size_t MAX_NUM_APP_RECORDS = 100;
+ // The number of apps to remove when mAppStats fills up.
+ static const size_t APP_RECORD_HEADROOM = 10;
private:
// Friend class for testing.
@@ -55,6 +60,10 @@ private:
static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag,
AStatsEventList* data,
void* cookie);
+
+ // Remove old packages from mAppStats.
+ void purgeOldDriverStats();
+
// Pull global into into global atom.
AStatsManager_PullAtomCallbackReturn pullGlobalInfoAtom(AStatsEventList* data);
// Pull app into into app atom.
@@ -68,9 +77,6 @@ private:
// Registers statsd callbacks if they have not already been registered
void registerStatsdCallbacksIfNeeded();
- // Below limits the memory usage of GpuStats to be less than 10KB. This is
- // the preferred number for statsd while maintaining nice data quality.
- static const size_t MAX_NUM_APP_RECORDS = 100;
// GpuStats access should be guarded by mLock.
std::mutex mLock;
// True if statsd callbacks have been registered.
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 37ebeae18d..20c8ccf9bf 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -17,6 +17,7 @@
#undef LOG_TAG
#define LOG_TAG "gpuservice_unittest"
+#include <unistd.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
#include <gpustats/GpuStats.h>
@@ -221,6 +222,51 @@ TEST_F(GpuStatsTest, canInsertTargetStatsAfterProperSetup) {
EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1"));
}
+// Verify we always have the most recently used apps in mAppStats, even when we fill it.
+TEST_F(GpuStatsTest, canInsertMoreThanMaxNumAppRecords) {
+ constexpr int kNumExtraApps = 15;
+ static_assert(kNumExtraApps > GpuStats::APP_RECORD_HEADROOM);
+
+ // Insert stats for GpuStats::MAX_NUM_APP_RECORDS so we fill it up.
+ for (int i = 0; i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps; ++i) {
+ std::stringstream nameStream;
+ nameStream << "testapp" << "_" << i;
+ std::string fullPkgName = nameStream.str();
+
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME,
+ fullPkgName, VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+ mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::CPU_VULKAN_IN_USE, 0);
+ mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::FALSE_PREROTATION, 0);
+ mGpuStats->insertTargetStats(fullPkgName, BUILTIN_DRIVER_VER_CODE,
+ GpuStatsInfo::Stats::GLES_1_IN_USE, 0);
+
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str()));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("cpuVulkanInUse = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("falsePrerotation = 1"));
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr("gles1InUse = 1"));
+ }
+
+ // mAppStats purges GpuStats::APP_RECORD_HEADROOM apps removed everytime it's filled up.
+ int numPurges = kNumExtraApps / GpuStats::APP_RECORD_HEADROOM;
+ numPurges += (kNumExtraApps % GpuStats::APP_RECORD_HEADROOM) == 0 ? 0 : 1;
+
+ // Verify the remaining apps are present.
+ for (int i = numPurges * GpuStats::APP_RECORD_HEADROOM;
+ i < GpuStats::MAX_NUM_APP_RECORDS + kNumExtraApps;
+ ++i) {
+ std::stringstream nameStream;
+ // Add a newline to search for the exact package name.
+ nameStream << "testapp" << "_" << i << "\n";
+ std::string fullPkgName = nameStream.str();
+
+ EXPECT_THAT(inputCommand(InputCommand::DUMP_APP), HasSubstr(fullPkgName.c_str()));
+ }
+}
+
TEST_F(GpuStatsTest, canDumpAllBeforeClearAll) {
mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c233bf06cf..ec31afe367 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -326,7 +326,7 @@ void SensorDevice::reconnect() {
mActivationCount.clear();
mSensorList.clear();
- if (connectHidlServiceV2_0() == HalConnectionStatus::CONNECTED) {
+ if (connectHidlService()) {
initializeSensorList();
if (sensorHandlesChanged(previousSensorList, mSensorList)) {
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 575e70d779..39d7bd948d 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -3,7 +3,7 @@ service surfaceflinger /system/bin/surfaceflinger
user system
group graphics drmrpc readproc
capabilities SYS_NICE
- onrestart restart zygote
+ onrestart restart --only-if-running zygote
task_profiles HighPerformance
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0