From c512ad85dc5788608920c995b0e3050d7dae012f Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:47:14 +0000 Subject: [PATCH] Fix Android native build failures in Oboe and Vulkan bridges - Fixed 'reportActualWorkDuration' build error in oboe_bridge.cpp by removing manual ADPF reporting (now handled internally by Oboe main). - Resolved 'byte' type errors in vulkan_bridge.cpp by adding a typedef for uint8_t. - Ensured binary compatibility with C# P/Invoke signatures by using the custom 'byte' type for native exports. - Updated AGENTS.md with current ADPF integration guidelines. --- AGENTS.md | 3 ++- osu.Android/Native/oboe_bridge.cpp | 15 +++++---------- osu.Android/Native/vulkan_bridge.h | 4 +++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3b1abe06b588..f217395d3c5f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,8 @@ Do not attempt to include internal Oboe headers for CPU affinity. Instead, use standard Linux `sched_setaffinity` in `oboe_bridge.cpp` to pin the audio callback thread to high-performance cores (typically the higher-indexed half of available cores in Android big.LITTLE architectures). ## ADPF Integration -The bridge uses `stream_->reportActualWorkDuration()` within the audio callback. This is critical for the Android Dynamic Performance Framework (ADPF) to adjust CPU frequencies accurately for low-latency audio without underruns. +Oboe handles ADPF (Android Dynamic Performance Framework) automatically when `setPerformanceHintEnabled(true)` is called during stream initialization. +Manual work duration reporting (`reportActualWorkDuration`) has been removed from the public Oboe API and should not be implemented in the bridge to avoid build errors and redundant reporting. ## Build Configuration `OBOE_ENABLE_FLOWGRAPH` is set to `OFF` in `CMakeLists.txt` to minimize binary size, as we perform all mixing in BASS and only use Oboe for final hardware delivery. diff --git a/osu.Android/Native/oboe_bridge.cpp b/osu.Android/Native/oboe_bridge.cpp index 15a960f4a6f1..8584ccd793eb 100644 --- a/osu.Android/Native/oboe_bridge.cpp +++ b/osu.Android/Native/oboe_bridge.cpp @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. #include "oboe_bridge.h" +#include "vulkan_bridge.h" #include #include #include @@ -170,8 +171,6 @@ void OboeBridge::setProvider(OboeAudioProvider provider) { oboe::DataCallbackResult OboeBridge::onAudioReady( oboe::AudioStream* stream, void* audioData, int32_t numFrames) { - // Record the start time of this callback for ADPF work duration reporting. - int64_t startTime = oboe::AudioClock::getNanoseconds(); OboeAudioProvider provider = provider_.load(std::memory_order_acquire); @@ -190,10 +189,6 @@ oboe::DataCallbackResult OboeBridge::onAudioReady( memset(audioData, 0, byteCount); } - // Reporting actual work duration helps ADPF (Android Dynamic Performance Framework) - // adjust CPU frequency precisely to handle the audio load without skipping. - int64_t endTime = oboe::AudioClock::getNanoseconds(); - if (stream->isPerformanceHintEnabled()) { stream->reportActualWorkDuration(endTime - startTime); } uint32_t count = callbackCount_.fetch_add(1, std::memory_order_relaxed); @@ -313,7 +308,7 @@ OSU_EXPORT void nOboeDestroy(intptr_t ptr) { if (ptr) delete reinterpret_cast(ptr); } -OSU_EXPORT unsigned char nOboeStart(intptr_t ptr) { +OSU_EXPORT byte nOboeStart(intptr_t ptr) { auto* bridge = reinterpret_cast(ptr); return (bridge && bridge->start()) ? 1 : 0; } @@ -328,7 +323,7 @@ OSU_EXPORT double nOboeGetLatencyMs(intptr_t ptr) { return bridge ? bridge->getOutputLatencyMs() : -1.0; } -OSU_EXPORT unsigned char nOboeIsActive(intptr_t ptr) { +OSU_EXPORT byte nOboeIsActive(intptr_t ptr) { auto* bridge = reinterpret_cast(ptr); return (bridge && bridge->isActive()) ? 1 : 0; } @@ -348,12 +343,12 @@ OSU_EXPORT int nOboeGetBufferSizeInFrames(intptr_t ptr) { return bridge ? bridge->getBufferSizeInFrames() : 0; } -OSU_EXPORT unsigned char nOboeIsAAudio(intptr_t ptr) { +OSU_EXPORT byte nOboeIsAAudio(intptr_t ptr) { auto* bridge = reinterpret_cast(ptr); return (bridge && bridge->isAAudio()) ? 1 : 0; } -OSU_EXPORT unsigned char nOboeIsMMap(intptr_t ptr) { +OSU_EXPORT byte nOboeIsMMap(intptr_t ptr) { auto* bridge = reinterpret_cast(ptr); return (bridge && bridge->isMMap()) ? 1 : 0; } diff --git a/osu.Android/Native/vulkan_bridge.h b/osu.Android/Native/vulkan_bridge.h index 0d867a129393..ccb9a843e09b 100644 --- a/osu.Android/Native/vulkan_bridge.h +++ b/osu.Android/Native/vulkan_bridge.h @@ -4,8 +4,10 @@ #pragma once #include -#include #include +#include + +typedef uint8_t byte; /// Lightweight Vulkan capability probe for Android. /// Requires Vulkan 1.3 as minimum for full feature detection (dynamic rendering,