diff options
| -rw-r--r-- | cmds/atrace/atrace.rc | 280 | ||||
| -rw-r--r-- | libs/binder/ndk/Android.bp | 2 | ||||
| -rw-r--r-- | libs/binder/ndk/include_cpp/android/binder_parcel_utils.h | 649 | ||||
| -rw-r--r-- | libs/binder/rust/src/binder.rs | 57 | ||||
| -rw-r--r-- | libs/binder/rust/src/lib.rs | 4 | ||||
| -rw-r--r-- | libs/binder/rust/tests/integration.rs | 108 | ||||
| -rw-r--r-- | libs/binder/tests/parcel_fuzzer/binder_ndk.cpp | 16 | ||||
| -rw-r--r-- | libs/graphicsenv/GpuStatsInfo.cpp | 3 | ||||
| -rw-r--r-- | libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h | 6 | ||||
| -rw-r--r-- | services/gpuservice/gpustats/GpuStats.cpp | 48 | ||||
| -rw-r--r-- | services/gpuservice/gpustats/include/gpustats/GpuStats.h | 12 | ||||
| -rw-r--r-- | services/gpuservice/tests/unittests/GpuStatsTest.cpp | 46 | ||||
| -rw-r--r-- | services/sensorservice/SensorDevice.cpp | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/surfaceflinger.rc | 2 |
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 |