Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Oboe Audio Bridge Optimizations

## CPU Affinity Pinning
As of Oboe `main` branch (post-1.9.0), internal headers like `common/Process.h` have been removed.
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.

## 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.
2 changes: 0 additions & 2 deletions osu.Android/Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ add_library(osu_native SHARED
vulkan_bridge.cpp
)

# Add Oboe internal headers to include path for Process.h (CPU affinity).
target_include_directories(osu_native PRIVATE ${oboe_SOURCE_DIR}/src)

target_link_libraries(osu_native
${OBOE_LIB}
Expand Down
27 changes: 18 additions & 9 deletions osu.Android/Native/oboe_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#include "oboe_bridge.h"
#include <oboe/OboeExtensions.h>
#include <oboe/AudioClock.h>
#include <common/Process.h>
#include <sched.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <android/log.h>
#include <cstdint>
#include <cstring>
Expand Down Expand Up @@ -205,15 +207,22 @@ oboe::DataCallbackResult OboeBridge::onAudioReady(

// Attempt to set CPU affinity to high-performance cores.
if (!affinitySet_.load(std::memory_order_relaxed)) {
std::vector<int> exclusiveCores = oboe::Process::getExclusiveCores();

if (!exclusiveCores.empty()) {
oboe::Result result = oboe::Process::setThreadAffinity(
oboe::Process::getThreadId(),
exclusiveCores);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);

int num_cores = sysconf(_SC_NPROCESSORS_CONF);
if (num_cores > 0) {
// Target the "big" cores (higher indexed) for better performance.
// In big.LITTLE, indices 4-7 are typically the high-performance cores.
int start_core = std::max(0, num_cores / 2);
for (int i = start_core; i < num_cores; ++i) {
CPU_SET(i, &cpuset);
}

if (result == oboe::Result::OK) {
LOGI("Oboe audio thread pinned to exclusive cores");
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) == 0) {
LOGI("Oboe audio thread pinned to cores %d-%d", start_core, num_cores - 1);
} else {
LOGE("Failed to set thread affinity: %d", errno);
}
}
affinitySet_.store(true);
Expand Down
1 change: 1 addition & 0 deletions osu.Android/osu.Android.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.Android.props" />
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFramework>net10.0-android</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>osu.Android</RootNamespace>
Expand Down
Loading