From 95b919c0200cfc380cb92fb3dffcebdabcb7f91d Mon Sep 17 00:00:00 2001 From: Robert Wu <85952307+robertwu1@users.noreply.github.com> Date: Thu, 20 Nov 2025 21:05:48 -0800 Subject: [PATCH 1/6] WIP: Test potential APERF_HINT_HIGH_PERFORMANCE_AUDIO --- .../app/src/main/cpp/cpu/AudioWorkloadTest.h | 6 +- .../main/cpp/cpu/AudioWorkloadTestRunner.h | 36 ++++---- .../app/src/main/cpp/jni-bridge.cpp | 35 ++++++-- .../mobileer/oboetester/AudioStreamBase.java | 6 ++ .../oboetester/AudioWorkloadTestActivity.java | 9 +- .../AudioWorkloadTestRunnerActivity.java | 10 ++- .../oboetester/DynamicWorkloadActivity.java | 33 +++++++ .../com/mobileer/oboetester/NativeEngine.java | 2 + .../mobileer/oboetester/OboeAudioStream.java | 6 ++ .../layout/activity_audio_workload_test.xml | 7 ++ .../activity_audio_workload_test_runner.xml | 7 ++ .../res/layout/activity_dynamic_workload.xml | 7 ++ apps/OboeTester/docs/AutomatedTesting.md | 1 + include/oboe/AudioStream.h | 23 +++++ src/aaudio/AudioStreamAAudio.cpp | 3 +- src/common/AdpfWrapper.cpp | 85 ++++++++++++++++++- src/common/AdpfWrapper.h | 11 ++- 17 files changed, 257 insertions(+), 30 deletions(-) diff --git a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h index d375060a4..d15261e7b 100644 --- a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h +++ b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h @@ -149,7 +149,7 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { */ int32_t start(int32_t targetDurationMillis, int32_t numBursts, int32_t numVoices, int32_t alternateNumVoices, int32_t alternatingPeriodMs, bool adpfEnabled, - bool adpfWorkloadIncreaseEnabled, bool hearWorkload) { + bool adpfWorkloadIncreaseEnabled, bool hearWorkload, bool highPerformanceAudio) { std::lock_guard lock(mStreamLock); if (!mStream) { LOGE("Error: Stream not open."); @@ -176,6 +176,10 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { mHearWorkload = hearWorkload; mAdpfWorkloadIncreaseEnabled = adpfWorkloadIncreaseEnabled; mStream->setPerformanceHintEnabled(adpfEnabled); + // Apply performance hint configuration if requested via runner flags. + oboe::PerformanceHintConfig cfg; + cfg.highPerformanceAudio = highPerformanceAudio; + mStream->setPerformanceHintConfig(cfg); mStream->setBufferSizeInFrames(mNumBursts * mFramesPerBurst); mBufferSizeInFrames = mStream->getBufferSizeInFrames(); oboe::Result result = mStream->start(); diff --git a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h index f50f79091..7486297d2 100644 --- a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h +++ b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h @@ -67,14 +67,15 @@ class AudioWorkloadTestRunner { * stream). */ int32_t start( - int32_t targetDurationMs, - int32_t numBursts, - int32_t numVoices, - int32_t alternateNumVoices, - int32_t alternatingPeriodMs, - bool adpfEnabled, - bool adpfWorkloadIncreaseEnabled, - bool hearWorkload) { + int32_t targetDurationMs, + int32_t numBursts, + int32_t numVoices, + int32_t alternateNumVoices, + int32_t alternatingPeriodMs, + bool adpfEnabled, + bool adpfWorkloadIncreaseEnabled, + bool hearWorkload, + bool highPerformanceAudio) { if (mIsRunning) { LOGE("Error: Test already running."); return -1; @@ -90,15 +91,16 @@ class AudioWorkloadTestRunner { mIsDone = false; mResult = 0; - int32_t result = mAudioWorkloadTest.start( - targetDurationMs, - numBursts, - numVoices, - alternateNumVoices, - alternatingPeriodMs, - adpfEnabled, - adpfWorkloadIncreaseEnabled, - hearWorkload); + int32_t result = mAudioWorkloadTest.start( + targetDurationMs, + numBursts, + numVoices, + alternateNumVoices, + alternatingPeriodMs, + adpfEnabled, + adpfWorkloadIncreaseEnabled, + hearWorkload, + highPerformanceAudio); if (result != static_cast(oboe::Result::OK)) { mResult = -1; diff --git a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp index bdea4e332..ad45c64e5 100644 --- a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp +++ b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp @@ -151,6 +151,11 @@ Java_com_mobileer_oboetester_NativeEngine_getCpuCount(JNIEnv *env, jclass type) return sysconf(_SC_NPROCESSORS_CONF); } +JNIEXPORT jboolean JNICALL +Java_com_mobileer_oboetester_NativeEngine_isHighPerformanceAudioSupported(JNIEnv *env, jclass type) { + return oboe::AdpfWrapper::isHighPerformanceAudioSupported(); +} + JNIEXPORT void JNICALL Java_com_mobileer_oboetester_NativeEngine_setCpuAffinityMask(JNIEnv *env, jclass type, @@ -352,6 +357,17 @@ Java_com_mobileer_oboetester_OboeAudioStream_setPerformanceHintEnabled( } } +JNIEXPORT void JNICALL +Java_com_mobileer_oboetester_OboeAudioStream_setPerformanceHintConfig( + JNIEnv *env, jobject, jint streamIndex, jboolean highPerformance) { + std::shared_ptr oboeStream = engine.getCurrentActivity()->getStream(streamIndex); + if (oboeStream != nullptr) { + oboe::PerformanceHintConfig cfg; + cfg.highPerformanceAudio = (highPerformance == JNI_TRUE); + oboeStream->setPerformanceHintConfig(cfg); + } +} + JNIEXPORT jint JNICALL Java_com_mobileer_oboetester_OboeAudioStream_getBufferCapacityInFrames( JNIEnv *env, jobject, jint streamIndex) { @@ -1206,10 +1222,10 @@ JNIEXPORT jint JNICALL Java_com_mobileer_oboetester_AudioWorkloadTestActivity_start(JNIEnv *env, jobject thiz, jint targetDurationMs, jint numBursts, jint numVoices, jint numAlternateVoices, jint alternatingPeriodMs, jboolean adpfEnabled, jboolean adpfWorkloadIncreaseEnabled, - jboolean hearWorkload) { + jboolean hearWorkload, jboolean highPerformanceAudio) { return sAudioWorkload.start(targetDurationMs, numBursts, numVoices, numAlternateVoices, alternatingPeriodMs, adpfEnabled, - adpfWorkloadIncreaseEnabled, hearWorkload); + adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio); } JNIEXPORT jint JNICALL @@ -1437,10 +1453,19 @@ Java_com_mobileer_oboetester_AudioWorkloadTestRunnerActivity_start(JNIEnv *env, jint alternatingPeriodMillis, jboolean adpfEnabled, jboolean adpfWorkloadIncreaseEnabled, - jboolean hearWorkload) { - return sAudioWorkloadRunner.start(targetDurationMs, numBursts, numVoices, + jboolean hearWorkload, + jboolean highPerformanceAudio) { + int32_t result = sAudioWorkloadRunner.start(targetDurationMs, numBursts, numVoices, alternateNumVoices, alternatingPeriodMillis, adpfEnabled, - adpfWorkloadIncreaseEnabled, hearWorkload); + adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio); + // When the runner starts, set performance hint config on the active stream + std::shared_ptr oboeStream = engine.getCurrentActivity()->getStream(0); + if (oboeStream != nullptr) { + oboe::PerformanceHintConfig cfg; + cfg.highPerformanceAudio = (highPerformanceAudio == JNI_TRUE); + oboeStream->setPerformanceHintConfig(cfg); + } + return result; } JNIEXPORT jboolean JNICALL diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioStreamBase.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioStreamBase.java index f4915fc05..785133d94 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioStreamBase.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioStreamBase.java @@ -88,6 +88,12 @@ public void setPerformanceHintEnabled(boolean checked) { } public void setHearWorkload(boolean checked) { } + /** + * Configure performance hint options for this stream. Default implementation is no-op. + * @param highPerformance true to request high performance audio mode when creating the session. + */ + public void setPerformanceHintConfig(boolean highPerformance) { + } public int notifyWorkloadIncrease(boolean cpu, boolean gpu) { return -1; } diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java index ae144f156..ab7d6266a 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java @@ -47,6 +47,7 @@ public class AudioWorkloadTestActivity extends BaseOboeTesterActivity { private CheckBox mEnableAdpfBox; private CheckBox mEnableAdpfWorkloadIncreaseBox; private CheckBox mHearWorkloadBox; + private CheckBox mHighPerformanceAudioBox; private int mCpuCount; private LinearLayout mAffinityLayout; @@ -149,6 +150,7 @@ protected void onCreate(Bundle savedInstanceState) { mEnableAdpfBox = (CheckBox) findViewById(R.id.enable_adpf); mEnableAdpfWorkloadIncreaseBox = (CheckBox) findViewById(R.id.enable_adpf_workload_increase); mHearWorkloadBox = (CheckBox) findViewById(R.id.hear_workload); + mHighPerformanceAudioBox = (CheckBox) findViewById(R.id.high_performance_audio); mOpenButton = (Button) findViewById(R.id.button_open); mStartButton = (Button) findViewById(R.id.button_start); @@ -224,7 +226,8 @@ public void startTest(View view) { int result = start(mTargetDurationMsSlider.getValue(), mNumBurstsSlider.getValue(), mNumVoicesSlider.getValue(), mAlternateNumVoicesSlider.getValue(), mAlternatingPeriodMsSlider.getValue(), mEnableAdpfBox.isChecked(), - mEnableAdpfWorkloadIncreaseBox.isChecked(), mHearWorkloadBox.isChecked()); + mEnableAdpfWorkloadIncreaseBox.isChecked(), mHearWorkloadBox.isChecked(), + mHighPerformanceAudioBox.isChecked()); if (result != OPERATION_SUCCESS) { showErrorToast("start failed! Error:" + result); return; @@ -318,6 +321,7 @@ public void enableParamsUI(boolean enabled) { mEnableAdpfBox.setEnabled(enabled); mEnableAdpfWorkloadIncreaseBox.setEnabled(enabled); mHearWorkloadBox.setEnabled(enabled); + mHighPerformanceAudioBox.setEnabled(enabled); } public void updateStreamInfoView() { @@ -331,7 +335,8 @@ public void updateStreamInfoView() { private native int getBufferSizeInFrames(); private native int start(int targetDurationMs, int numBursts, int numVoices, int numAlternateVoices, int alternatingPeriodMs, boolean adpfEnabled, - boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload); + boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload, + boolean highPerformanceAudio); private native int getCpuCount(); private native int setCpuAffinityForCallback(int mask); private native int getXRunCount(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java index 79924b4dd..8a7e716ce 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java @@ -38,6 +38,7 @@ public class AudioWorkloadTestRunnerActivity extends BaseOboeTesterActivity { private CheckBox mEnableAdpfBox; private CheckBox mEnableAdpfWorkloadIncreaseBox; private CheckBox mHearWorkloadBox; + private CheckBox mHighPerformanceAudioBox; private Button mStartButton; private Button mStopButton; @@ -79,6 +80,7 @@ protected void onCreate(Bundle savedInstanceState) { mEnableAdpfBox = findViewById(R.id.enable_adpf); mEnableAdpfWorkloadIncreaseBox = findViewById(R.id.enable_adpf_workload_increase); mHearWorkloadBox = findViewById(R.id.hear_workload); + mHighPerformanceAudioBox = findViewById(R.id.high_performance_audio); mStartButton = findViewById(R.id.button_start_test); mStopButton = findViewById(R.id.button_stop_test); @@ -107,9 +109,11 @@ public void startTest(View view) { boolean adpfEnabled = mEnableAdpfBox.isChecked(); boolean adpfWorkloadIncreaseEnabled = mEnableAdpfWorkloadIncreaseBox.isChecked(); boolean hearWorkload = mHearWorkloadBox.isChecked(); + boolean highPerformanceAudio = mHighPerformanceAudioBox.isChecked(); + int result = start(targetDurationMs, numBursts, numVoices, alternateNumVoices, - alternatingPeriodMs, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload); + alternatingPeriodMs, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio); if (result != OPERATION_SUCCESS) { showErrorToast("start failed! Error:" + result); return; @@ -144,6 +148,7 @@ public void enableParamsUI(boolean enabled) { mEnableAdpfBox.setEnabled(enabled); mEnableAdpfWorkloadIncreaseBox.setEnabled(enabled); mHearWorkloadBox.setEnabled(enabled); + mHighPerformanceAudioBox.setEnabled(enabled); } private void updateResultTextView() { @@ -160,7 +165,8 @@ private void updateResultTextView() { public native int start(int targetDurationMs, int numBursts, int numVoices, int alternateNumVoices, int alternatingPeriodMs, boolean adpfEnabled, - boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload); + boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload, + boolean highPerformanceAudio); public native boolean stopIfDone(); public native String getStatus(); public native int stop(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java index 67d2375c0..2be32e7ed 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java @@ -65,6 +65,8 @@ public class DynamicWorkloadActivity extends TestOutputActivityBase { public static final boolean VALUE_DEFAULT_SCROLL_GRAPHICS = false; public static final String KEY_USE_WORKLOAD_INCREASE_API = "use_workload_increase_api"; public static final boolean VALUE_DEFAULT_USE_WORKLOAD_INCREASE_API = false; + public static final String KEY_HIGH_PERFORMANCE_AUDIO = "high_performance_audio"; + public static final boolean VALUE_DEFAULT_HIGH_PERFORMANCE_AUDIO = false; private Button mStopButton; private Button mStartButton; @@ -79,6 +81,7 @@ public class DynamicWorkloadActivity extends TestOutputActivityBase { private CheckBox mUseAltAdpfBox; private CheckBox mPerfHintBox; private CheckBox mWorkloadReportBox; + private CheckBox mHighPerformanceAudioBox; private boolean mDrawChartAlways = true; private CheckBox mDrawAlwaysBox; private CheckBox mSustainedPerformanceModeBox; @@ -88,6 +91,7 @@ public class DynamicWorkloadActivity extends TestOutputActivityBase { private boolean mShouldUseWorkloadReporting; private boolean mEnableWorkloadIncreaseApi; private int mLastNotifyWorkloadResult; + private boolean mShouldUseHighPerformanceAudio; private static final int WORKLOAD_LOW = 1; private int mWorkloadHigh; // this will get set later @@ -309,6 +313,15 @@ public void onClick(View view) { mPerfHintBox = (CheckBox) findViewById(R.id.enable_perf_hint); mWorkloadReportBox = (CheckBox) findViewById(R.id.enable_workload_report); + mHighPerformanceAudioBox = (CheckBox) findViewById(R.id.high_performance_audio); + + // If the platform does not support the high-performance-audio APERF feature, + // hide or disable the UI control so users don't attempt to enable it. + boolean hpSupported = NativeEngine.isHighPerformanceAudioSupported(); + if (!hpSupported && mHighPerformanceAudioBox != null) { + mHighPerformanceAudioBox.setEnabled(false); + mHighPerformanceAudioBox.setVisibility(View.GONE); + } // TODO remove when finished with ADPF experiments. mUseAltAdpfBox = (CheckBox) findViewById(R.id.use_alternative_adpf); @@ -343,6 +356,13 @@ public void onClick(View view) { }); mWorkloadIncreaseApiBox.setEnabled(mEnableWorkloadIncreaseApi); + if (mHighPerformanceAudioBox != null) { + mHighPerformanceAudioBox.setOnClickListener(buttonView -> { + CheckBox checkBox = (CheckBox) buttonView; + mAudioOutTester.getCurrentAudioStream().setPerformanceHintConfig(checkBox.isChecked()); + }); + } + CheckBox hearWorkloadBox = (CheckBox) findViewById(R.id.hear_workload); hearWorkloadBox.setOnClickListener(buttonView -> { CheckBox checkBox = (CheckBox) buttonView; @@ -395,6 +415,13 @@ private void setWorkloadReportingEnabled(boolean enabled) { NativeEngine.setWorkloadReportingEnabled(enabled); } + private void setHighPerformanceAudio(boolean enabled) { + mShouldUseHighPerformanceAudio = enabled; + if (mAudioOutTester != null && mAudioOutTester.getCurrentAudioStream() != null) { + mAudioOutTester.getCurrentAudioStream().setPerformanceHintConfig(enabled); + } + } + private void setNotifyWorkloadIncreaseEnabled(boolean enabled) { NativeEngine.setNotifyWorkloadIncreaseEnabled(enabled); } @@ -403,6 +430,7 @@ private void updateButtons(boolean running) { mStartButton.setEnabled(!running); mStopButton.setEnabled(running); mPerfHintBox.setEnabled(running); + mHighPerformanceAudioBox.setEnabled(running); mWorkloadReportBox.setEnabled(running && mShouldUseADPF); mWorkloadIncreaseApiBox.setEnabled(running && mShouldUseADPF); } @@ -434,6 +462,7 @@ private void startTest() { } try { super.startAudio(); + setHighPerformanceAudio(mShouldUseHighPerformanceAudio); setPerformanceHintEnabled(mShouldUseADPF); updateButtons(true); postResult("Running test"); @@ -477,10 +506,14 @@ public void startTestUsingBundle() { VALUE_DEFAULT_SCROLL_GRAPHICS); mEnableWorkloadIncreaseApi = mBundleFromIntent.getBoolean(KEY_USE_WORKLOAD_INCREASE_API, VALUE_DEFAULT_USE_WORKLOAD_INCREASE_API); + mShouldUseHighPerformanceAudio = mBundleFromIntent.getBoolean(KEY_HIGH_PERFORMANCE_AUDIO, + VALUE_DEFAULT_HIGH_PERFORMANCE_AUDIO); startTest(); runOnUiThread(() -> { + mHighPerformanceAudioBox.setChecked(mShouldUseHighPerformanceAudio); + setHighPerformanceAudio(mShouldUseHighPerformanceAudio); mPerfHintBox.setChecked(mShouldUseADPF); setPerformanceHintEnabled(mShouldUseADPF); mWorkloadReportBox.setChecked(mShouldUseWorkloadReporting); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java index 2a5f36b7f..588dca4a5 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java @@ -6,6 +6,8 @@ public class NativeEngine { static native boolean isMMapExclusiveSupported(); + static native boolean isHighPerformanceAudioSupported(); + static native void setWorkaroundsEnabled(boolean enabled); static native boolean areWorkaroundsEnabled(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java index a151af09d..bf6008aa2 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java @@ -171,6 +171,12 @@ public void setPerformanceHintEnabled(boolean checked) { } private native void setPerformanceHintEnabled(int streamIndex, boolean checked); + @Override + public void setPerformanceHintConfig(boolean highPerformance) { + setPerformanceHintConfig(mStreamIndex, highPerformance); + } + private native void setPerformanceHintConfig(int streamIndex, boolean highPerformance); + @Override public void setHearWorkload(boolean checked) { setHearWorkload(mStreamIndex, checked); diff --git a/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml b/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml index b041938ed..0c84787da 100644 --- a/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml +++ b/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml @@ -148,6 +148,13 @@ android:layout_height="wrap_content" android:layout_marginRight="8sp" android:text="Hear Workload" /> + + diff --git a/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test_runner.xml b/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test_runner.xml index a36a12d7b..ad5c30364 100644 --- a/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test_runner.xml +++ b/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test_runner.xml @@ -140,6 +140,13 @@ android:layout_height="wrap_content" android:layout_marginRight="8sp" android:text="Hear Workload" /> + + + + mWeakThis; // weak pointer to this object + // Performance hint configuration for this stream. + PerformanceHintConfig mPerformanceHintConfig; /** * Number of frames which have been written into the stream diff --git a/src/aaudio/AudioStreamAAudio.cpp b/src/aaudio/AudioStreamAAudio.cpp index d8fa4e43b..06acd9925 100644 --- a/src/aaudio/AudioStreamAAudio.cpp +++ b/src/aaudio/AudioStreamAAudio.cpp @@ -283,7 +283,8 @@ void AudioStreamAAudio::beginPerformanceHintInCallback() { if (!mAdpfOpenAttempted) { int64_t targetDurationNanos = (mFramesPerBurst * 1e9) / getSampleRate(); // This has to be called from the callback thread so we get the right TID. - int adpfResult = mAdpfWrapper.open(gettid(), targetDurationNanos); + int adpfResult = mAdpfWrapper.open(gettid(), targetDurationNanos, + mPerformanceHintConfig.highPerformanceAudio); if (adpfResult < 0) { LOGW("WARNING ADPF not supported, %d\n", adpfResult); } else { diff --git a/src/common/AdpfWrapper.cpp b/src/common/AdpfWrapper.cpp index 4fcae60c9..cb61560a2 100644 --- a/src/common/AdpfWrapper.cpp +++ b/src/common/AdpfWrapper.cpp @@ -35,6 +35,13 @@ typedef void (*APH_closeSession)(APerformanceHintSession* session); typedef int (*APH_notifyWorkloadIncrease)(APerformanceHintSession*, bool, bool, const char*); typedef int (*APH_notifyWorkloadSpike)(APerformanceHintSession*, bool, bool, const char*); typedef int (*APH_notifyWorkloadReset)(APerformanceHintSession*, bool, bool, const char*); +typedef int (*APH_createSessionUsingConfig)(APerformanceHintManager*, void* /*ASessionCreationConfig*/, APerformanceHintSession**); +typedef void* (*APH_sessionConfig_create)(); +typedef void (*APH_sessionConfig_release)(void*); +typedef void (*APH_sessionConfig_setTids)(void*, const pid_t*, size_t); +typedef void (*APH_sessionConfig_setTargetWorkDurationNanos)(void*, int64_t); +typedef void (*APH_sessionConfig_setHighPerformanceAudio)(void*, bool); +typedef bool (*APH_isFeatureSupported)(void* /*APerformanceHintFeature*/); static bool gAPerformanceHintBindingInitialized = false; static APH_getManager gAPH_getManagerFn = nullptr; @@ -44,11 +51,26 @@ static APH_closeSession gAPH_closeSessionFn = nullptr; static APH_notifyWorkloadIncrease gAPH_notifyWorkloadIncreaseFn = nullptr; static APH_notifyWorkloadSpike gAPH_notifyWorkloadSpikeFn = nullptr; static APH_notifyWorkloadReset gAPH_notifyWorkloadResetFn = nullptr; +static APH_createSessionUsingConfig gAPH_createSessionUsingConfigFn = nullptr; +static APH_sessionConfig_create gAPH_sessionConfigCreateFn = nullptr; +static APH_sessionConfig_release gAPH_sessionConfigReleaseFn = nullptr; +static APH_sessionConfig_setTids gAPH_sessionConfigSetTidsFn = nullptr; +static APH_sessionConfig_setTargetWorkDurationNanos gAPH_sessionConfigSetTargetWorkDurationNanosFn = nullptr; +static APH_sessionConfig_setHighPerformanceAudio gAPH_sessionConfigSetHighPerformanceAudioFn = nullptr; +static APH_isFeatureSupported gAPH_isFeatureSupportedFn = nullptr; #ifndef __ANDROID_API_B__ #define __ANDROID_API_B__ 36 #endif +#ifndef APERF_HINT_SESSIONS +#define APERF_HINT_SESSIONS 0 +#endif + +#ifndef APERF_HINT_HIGH_PERFORMANCE_AUDIO +#define APERF_HINT_HIGH_PERFORMANCE_AUDIO 6 +#endif + static int loadAphFunctions() { if (gAPerformanceHintBindingInitialized) return true; @@ -95,6 +117,20 @@ static int loadAphFunctions() { if (gAPH_notifyWorkloadResetFn == nullptr) { return -1007; } + + // Optional config-based session creation (API 36+). These may be missing on older + // platforms or pre-release builds; load them if available. + gAPH_createSessionUsingConfigFn = (APH_createSessionUsingConfig)dlsym( + handle_, "APerformanceHint_createSessionUsingConfig"); + gAPH_sessionConfigCreateFn = (APH_sessionConfig_create)dlsym(handle_, "ASessionCreationConfig_create"); + gAPH_sessionConfigReleaseFn = (APH_sessionConfig_release)dlsym(handle_, "ASessionCreationConfig_release"); + gAPH_sessionConfigSetTidsFn = (APH_sessionConfig_setTids)dlsym(handle_, "ASessionCreationConfig_setTids"); + gAPH_sessionConfigSetTargetWorkDurationNanosFn = (APH_sessionConfig_setTargetWorkDurationNanos)dlsym( + handle_, "ASessionCreationConfig_setTargetWorkDurationNanos"); + gAPH_sessionConfigSetHighPerformanceAudioFn = (APH_sessionConfig_setHighPerformanceAudio)dlsym( + handle_, "ASessionCreationConfig_setHighPerformanceAudio"); + gAPH_isFeatureSupportedFn = (APH_isFeatureSupported)dlsym( + handle_, "APerformanceHint_isFeatureSupported"); } gAPerformanceHintBindingInitialized = true; @@ -104,8 +140,20 @@ static int loadAphFunctions() { bool AdpfWrapper::sUseAlternativeHack = false; // TODO remove hack +bool AdpfWrapper::isHighPerformanceAudioSupported() { + // Ensure the performance hint functions are loaded. + int result = loadAphFunctions(); + if (result < 0) return false; + if (gAPH_isFeatureSupportedFn == nullptr) return false; + // The binding expects a feature identifier; we use the integer constant + // APERF_HINT_HIGH_PERFORMANCE_AUDIO cast into the expected parameter type. + return gAPH_isFeatureSupportedFn( + reinterpret_cast(static_cast(APERF_HINT_HIGH_PERFORMANCE_AUDIO))); +} + int AdpfWrapper::open(pid_t threadId, - int64_t targetDurationNanos) { + int64_t targetDurationNanos, + bool highPerformanceAudio) { std::lock_guard lock(mLock); int result = loadAphFunctions(); if (result < 0) return result; @@ -120,6 +168,41 @@ int AdpfWrapper::open(pid_t threadId, // algorithm that is not based on PID. targetDurationNanos = (targetDurationNanos & ~0xFF) | 0xA5; } + // If caller requested highPerformanceAudio and we have the newer config-based + // session creation API, try to create a session with a creation config. + if (highPerformanceAudio && gAPH_isFeatureSupportedFn != nullptr + && gAPH_isFeatureSupportedFn( + reinterpret_cast(static_cast(APERF_HINT_SESSIONS))) + && gAPH_isFeatureSupportedFn( + reinterpret_cast(static_cast(APERF_HINT_HIGH_PERFORMANCE_AUDIO))) + && gAPH_createSessionUsingConfigFn != nullptr + && gAPH_sessionConfigCreateFn != nullptr + && gAPH_sessionConfigReleaseFn != nullptr + && gAPH_sessionConfigSetTidsFn != nullptr + && gAPH_sessionConfigSetTargetWorkDurationNanosFn != nullptr + && gAPH_sessionConfigSetHighPerformanceAudioFn != nullptr) { + + void* config = gAPH_sessionConfigCreateFn(); + if (config != nullptr) { + // set tids + gAPH_sessionConfigSetTidsFn(config, &thread32, 1); + // set target duration + gAPH_sessionConfigSetTargetWorkDurationNanosFn(config, targetDurationNanos); + // set high performance audio hint + gAPH_sessionConfigSetHighPerformanceAudioFn(config, true); + + APerformanceHintSession *sessionOut = nullptr; + int createResult = gAPH_createSessionUsingConfigFn(manager, config, &sessionOut); + // release config now + gAPH_sessionConfigReleaseFn(config); + if (createResult == 0 && sessionOut != nullptr) { + mHintSession = sessionOut; + return 0; + } + // otherwise fall through to legacy createSession + } + } + mHintSession = gAPH_createSessionFn(manager, &thread32, 1 /* size */, targetDurationNanos); if (mHintSession == nullptr) { return -1; diff --git a/src/common/AdpfWrapper.h b/src/common/AdpfWrapper.h index b12e0847c..bd5bcc02f 100644 --- a/src/common/AdpfWrapper.h +++ b/src/common/AdpfWrapper.h @@ -43,7 +43,8 @@ namespace oboe { * @return zero or negative error */ int open(pid_t threadId, - int64_t targetDurationNanos); + int64_t targetDurationNanos, + bool highPerformanceAudio = false); bool isOpen() const { return (mHintSession != nullptr); @@ -71,6 +72,14 @@ namespace oboe { sUseAlternativeHack = enabled; } + /** + * Return true if the platform reports support for the high-performance-audio + * feature (APerfHintFeature::APERF_HINT_HIGH_PERFORMANCE_AUDIO). + * This is a static helper that will attempt to bind to the native API if + * necessary. + */ + static bool isHighPerformanceAudioSupported(); + /** * Report the measured duration of a callback. * This is normally called by onEndCallback(). From 29e956c6a2518175f1ee2dad99a4db5cc00e0ea5 Mon Sep 17 00:00:00 2001 From: Robert Wu <85952307+robertwu1@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:49:04 -0800 Subject: [PATCH 2/6] rename to audio performance --- src/common/AdpfWrapper.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/common/AdpfWrapper.cpp b/src/common/AdpfWrapper.cpp index cb61560a2..b62bd40c5 100644 --- a/src/common/AdpfWrapper.cpp +++ b/src/common/AdpfWrapper.cpp @@ -40,7 +40,7 @@ typedef void* (*APH_sessionConfig_create)(); typedef void (*APH_sessionConfig_release)(void*); typedef void (*APH_sessionConfig_setTids)(void*, const pid_t*, size_t); typedef void (*APH_sessionConfig_setTargetWorkDurationNanos)(void*, int64_t); -typedef void (*APH_sessionConfig_setHighPerformanceAudio)(void*, bool); +typedef void (*APH_sessionConfig_setAudioPerformance)(void*, bool); typedef bool (*APH_isFeatureSupported)(void* /*APerformanceHintFeature*/); static bool gAPerformanceHintBindingInitialized = false; @@ -56,7 +56,7 @@ static APH_sessionConfig_create gAPH_sessionConfigCreateFn = nullptr; static APH_sessionConfig_release gAPH_sessionConfigReleaseFn = nullptr; static APH_sessionConfig_setTids gAPH_sessionConfigSetTidsFn = nullptr; static APH_sessionConfig_setTargetWorkDurationNanos gAPH_sessionConfigSetTargetWorkDurationNanosFn = nullptr; -static APH_sessionConfig_setHighPerformanceAudio gAPH_sessionConfigSetHighPerformanceAudioFn = nullptr; +static APH_sessionConfig_setAudioPerformance gAPH_sessionConfigSetAudioPerformanceFn = nullptr; static APH_isFeatureSupported gAPH_isFeatureSupportedFn = nullptr; #ifndef __ANDROID_API_B__ @@ -67,8 +67,8 @@ static APH_isFeatureSupported gAPH_isFeatureSupportedFn = nullptr; #define APERF_HINT_SESSIONS 0 #endif -#ifndef APERF_HINT_HIGH_PERFORMANCE_AUDIO -#define APERF_HINT_HIGH_PERFORMANCE_AUDIO 6 +#ifndef APERF_HINT_AUDIO_PERFORMANCE +#define APERF_HINT_AUDIO_PERFORMANCE 6 #endif static int loadAphFunctions() { @@ -127,8 +127,8 @@ static int loadAphFunctions() { gAPH_sessionConfigSetTidsFn = (APH_sessionConfig_setTids)dlsym(handle_, "ASessionCreationConfig_setTids"); gAPH_sessionConfigSetTargetWorkDurationNanosFn = (APH_sessionConfig_setTargetWorkDurationNanos)dlsym( handle_, "ASessionCreationConfig_setTargetWorkDurationNanos"); - gAPH_sessionConfigSetHighPerformanceAudioFn = (APH_sessionConfig_setHighPerformanceAudio)dlsym( - handle_, "ASessionCreationConfig_setHighPerformanceAudio"); + gAPH_sessionConfigSetAudioPerformanceFn = (APH_sessionConfig_setAudioPerformance)dlsym( + handle_, "ASessionCreationConfig_setAudioPerformance"); gAPH_isFeatureSupportedFn = (APH_isFeatureSupported)dlsym( handle_, "APerformanceHint_isFeatureSupported"); } @@ -146,9 +146,9 @@ bool AdpfWrapper::isHighPerformanceAudioSupported() { if (result < 0) return false; if (gAPH_isFeatureSupportedFn == nullptr) return false; // The binding expects a feature identifier; we use the integer constant - // APERF_HINT_HIGH_PERFORMANCE_AUDIO cast into the expected parameter type. + // APERF_HINT_AUDIO_PERFORMANCE cast into the expected parameter type. return gAPH_isFeatureSupportedFn( - reinterpret_cast(static_cast(APERF_HINT_HIGH_PERFORMANCE_AUDIO))); + reinterpret_cast(static_cast(APERF_HINT_AUDIO_PERFORMANCE))); } int AdpfWrapper::open(pid_t threadId, @@ -174,13 +174,13 @@ int AdpfWrapper::open(pid_t threadId, && gAPH_isFeatureSupportedFn( reinterpret_cast(static_cast(APERF_HINT_SESSIONS))) && gAPH_isFeatureSupportedFn( - reinterpret_cast(static_cast(APERF_HINT_HIGH_PERFORMANCE_AUDIO))) + reinterpret_cast(static_cast(APERF_HINT_AUDIO_PERFORMANCE))) && gAPH_createSessionUsingConfigFn != nullptr && gAPH_sessionConfigCreateFn != nullptr && gAPH_sessionConfigReleaseFn != nullptr && gAPH_sessionConfigSetTidsFn != nullptr && gAPH_sessionConfigSetTargetWorkDurationNanosFn != nullptr - && gAPH_sessionConfigSetHighPerformanceAudioFn != nullptr) { + && gAPH_sessionConfigSetAudioPerformanceFn != nullptr) { void* config = gAPH_sessionConfigCreateFn(); if (config != nullptr) { @@ -189,7 +189,7 @@ int AdpfWrapper::open(pid_t threadId, // set target duration gAPH_sessionConfigSetTargetWorkDurationNanosFn(config, targetDurationNanos); // set high performance audio hint - gAPH_sessionConfigSetHighPerformanceAudioFn(config, true); + gAPH_sessionConfigSetAudioPerformanceFn(config, true); APerformanceHintSession *sessionOut = nullptr; int createResult = gAPH_createSessionUsingConfigFn(manager, config, &sessionOut); From c8119b0f2c702a72f0e295a5c5216857ea864263 Mon Sep 17 00:00:00 2001 From: Robert Wu <85952307+robertwu1@users.noreply.github.com> Date: Thu, 8 Jan 2026 17:25:24 -0800 Subject: [PATCH 3/6] addd option to remove ADPF set duration --- .../app/src/main/cpp/NativeAudioContext.h | 7 +++++++ .../app/src/main/cpp/cpu/AudioWorkloadTest.h | 9 ++++++++- .../main/cpp/cpu/AudioWorkloadTestRunner.h | 6 ++++-- .../app/src/main/cpp/jni-bridge.cpp | 19 ++++++++++++++---- .../oboetester/AudioWorkloadTestActivity.java | 16 ++++++++++----- .../AudioWorkloadTestRunnerActivity.java | 11 +++++++--- .../oboetester/DynamicWorkloadActivity.java | 8 ++++++++ .../com/mobileer/oboetester/NativeEngine.java | 2 ++ .../layout/activity_audio_workload_test.xml | 19 ++++++++++++++++++ .../activity_audio_workload_test_runner.xml | 20 +++++++++++++++++++ .../res/layout/activity_dynamic_workload.xml | 20 +++++++++++++++++++ include/oboe/AudioStream.h | 7 +++++++ src/aaudio/AudioStreamAAudio.h | 5 +++++ src/common/AdpfWrapper.cpp | 6 ++++++ src/common/AdpfWrapper.h | 7 +++++++ 15 files changed, 147 insertions(+), 15 deletions(-) diff --git a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h index 740d36329..0cfc88573 100644 --- a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h +++ b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h @@ -341,6 +341,13 @@ class ActivityContext { oboeCallbackProxy->setNotifyWorkloadIncreaseEnabled(enabled); } + void setReportActualDurationEnabled(bool enabled) { + std::shared_ptr stream = getOutputStream(); + if (stream) { + stream->setReportActualDurationEnabled(enabled); + } + } + int32_t setBufferSizeInFrames(int streamIndex, int threshold); virtual void setupMemoryBuffer([[maybe_unused]] std::unique_ptr& buffer, diff --git a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h index d15261e7b..bc545f48a 100644 --- a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h +++ b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h @@ -98,6 +98,9 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { return static_cast(result); } + // Apply the current setting for reporting actual duration once the stream exists. + mStream->setReportActualDurationEnabled(mReportActualDurationEnabled); + mFramesPerBurst = mStream->getFramesPerBurst(); mSampleRate = mStream->getSampleRate(); mPreviousXRunCount = 0; @@ -149,7 +152,8 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { */ int32_t start(int32_t targetDurationMillis, int32_t numBursts, int32_t numVoices, int32_t alternateNumVoices, int32_t alternatingPeriodMs, bool adpfEnabled, - bool adpfWorkloadIncreaseEnabled, bool hearWorkload, bool highPerformanceAudio) { + bool adpfWorkloadIncreaseEnabled, bool hearWorkload, bool highPerformanceAudio, + bool reportActualDurationEnabled) { std::lock_guard lock(mStreamLock); if (!mStream) { LOGE("Error: Stream not open."); @@ -175,7 +179,9 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { mRunning = true; mHearWorkload = hearWorkload; mAdpfWorkloadIncreaseEnabled = adpfWorkloadIncreaseEnabled; + mReportActualDurationEnabled = reportActualDurationEnabled; mStream->setPerformanceHintEnabled(adpfEnabled); + mStream->setReportActualDurationEnabled(mReportActualDurationEnabled); // Apply performance hint configuration if requested via runner flags. oboe::PerformanceHintConfig cfg; cfg.highPerformanceAudio = highPerformanceAudio; @@ -426,6 +432,7 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { std::atomic mStartTimeMs{0}; std::atomic mHearWorkload{false}; std::atomic mAdpfWorkloadIncreaseEnabled{false}; + std::atomic mReportActualDurationEnabled{true}; // Lock to protect mCallbackStatistics std::mutex mStatisticsLock; diff --git a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h index 7486297d2..84bf2a5ca 100644 --- a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h +++ b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h @@ -75,7 +75,8 @@ class AudioWorkloadTestRunner { bool adpfEnabled, bool adpfWorkloadIncreaseEnabled, bool hearWorkload, - bool highPerformanceAudio) { + bool highPerformanceAudio, + bool reportActualDurationEnabled) { if (mIsRunning) { LOGE("Error: Test already running."); return -1; @@ -100,7 +101,8 @@ class AudioWorkloadTestRunner { adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, - highPerformanceAudio); + highPerformanceAudio, + reportActualDurationEnabled); if (result != static_cast(oboe::Result::OK)) { mResult = -1; diff --git a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp index ad45c64e5..af1017dec 100644 --- a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp +++ b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp @@ -325,6 +325,13 @@ Java_com_mobileer_oboetester_TestAudioActivity_setUseAlternativeAdpf(JNIEnv *env oboe::AdpfWrapper::setUseAlternative(enabled); } +JNIEXPORT void JNICALL +Java_com_mobileer_oboetester_NativeEngine_setReportActualDurationEnabled(JNIEnv *env, + jclass type, + jboolean enabled) { + engine.getCurrentActivity()->setReportActualDurationEnabled(enabled); +} + JNIEXPORT jint JNICALL Java_com_mobileer_oboetester_OboeAudioStream_setBufferSizeInFrames( JNIEnv *env, jobject, jint streamIndex, jint threshold) { @@ -1222,10 +1229,12 @@ JNIEXPORT jint JNICALL Java_com_mobileer_oboetester_AudioWorkloadTestActivity_start(JNIEnv *env, jobject thiz, jint targetDurationMs, jint numBursts, jint numVoices, jint numAlternateVoices, jint alternatingPeriodMs, jboolean adpfEnabled, jboolean adpfWorkloadIncreaseEnabled, - jboolean hearWorkload, jboolean highPerformanceAudio) { + jboolean hearWorkload, jboolean highPerformanceAudio, + jboolean reportActualDurationEnabled) { return sAudioWorkload.start(targetDurationMs, numBursts, numVoices, numAlternateVoices, alternatingPeriodMs, adpfEnabled, - adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio); + adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio, + reportActualDurationEnabled); } JNIEXPORT jint JNICALL @@ -1454,10 +1463,12 @@ Java_com_mobileer_oboetester_AudioWorkloadTestRunnerActivity_start(JNIEnv *env, jboolean adpfEnabled, jboolean adpfWorkloadIncreaseEnabled, jboolean hearWorkload, - jboolean highPerformanceAudio) { + jboolean highPerformanceAudio, + jboolean reportActualDurationEnabled) { int32_t result = sAudioWorkloadRunner.start(targetDurationMs, numBursts, numVoices, alternateNumVoices, alternatingPeriodMillis, adpfEnabled, - adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio); + adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio, + reportActualDurationEnabled); // When the runner starts, set performance hint config on the active stream std::shared_ptr oboeStream = engine.getCurrentActivity()->getStream(0); if (oboeStream != nullptr) { diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java index ab7d6266a..bb4bd9296 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java @@ -48,6 +48,7 @@ public class AudioWorkloadTestActivity extends BaseOboeTesterActivity { private CheckBox mEnableAdpfWorkloadIncreaseBox; private CheckBox mHearWorkloadBox; private CheckBox mHighPerformanceAudioBox; + private CheckBox mDisableAdpfDurationBox; private int mCpuCount; private LinearLayout mAffinityLayout; @@ -152,6 +153,8 @@ protected void onCreate(Bundle savedInstanceState) { mHearWorkloadBox = (CheckBox) findViewById(R.id.hear_workload); mHighPerformanceAudioBox = (CheckBox) findViewById(R.id.high_performance_audio); + mDisableAdpfDurationBox = (CheckBox) findViewById(R.id.disable_adpf_duration); + mOpenButton = (Button) findViewById(R.id.button_open); mStartButton = (Button) findViewById(R.id.button_start); mStopButton = (Button) findViewById(R.id.button_stop); @@ -223,11 +226,13 @@ public void openAudio(View view) { } public void startTest(View view) { + boolean reportActualDurationEnabled = !mDisableAdpfDurationBox.isChecked(); + int result = start(mTargetDurationMsSlider.getValue(), mNumBurstsSlider.getValue(), - mNumVoicesSlider.getValue(), mAlternateNumVoicesSlider.getValue(), - mAlternatingPeriodMsSlider.getValue(), mEnableAdpfBox.isChecked(), - mEnableAdpfWorkloadIncreaseBox.isChecked(), mHearWorkloadBox.isChecked(), - mHighPerformanceAudioBox.isChecked()); + mNumVoicesSlider.getValue(), mAlternateNumVoicesSlider.getValue(), + mAlternatingPeriodMsSlider.getValue(), mEnableAdpfBox.isChecked(), + mEnableAdpfWorkloadIncreaseBox.isChecked(), mHearWorkloadBox.isChecked(), + mHighPerformanceAudioBox.isChecked(), reportActualDurationEnabled); if (result != OPERATION_SUCCESS) { showErrorToast("start failed! Error:" + result); return; @@ -322,6 +327,7 @@ public void enableParamsUI(boolean enabled) { mEnableAdpfWorkloadIncreaseBox.setEnabled(enabled); mHearWorkloadBox.setEnabled(enabled); mHighPerformanceAudioBox.setEnabled(enabled); + mDisableAdpfDurationBox.setEnabled(enabled); } public void updateStreamInfoView() { @@ -336,7 +342,7 @@ public void updateStreamInfoView() { private native int start(int targetDurationMs, int numBursts, int numVoices, int numAlternateVoices, int alternatingPeriodMs, boolean adpfEnabled, boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload, - boolean highPerformanceAudio); + boolean highPerformanceAudio, boolean reportActualDurationEnabled); private native int getCpuCount(); private native int setCpuAffinityForCallback(int mask); private native int getXRunCount(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java index 8a7e716ce..4ed127a06 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java @@ -39,6 +39,7 @@ public class AudioWorkloadTestRunnerActivity extends BaseOboeTesterActivity { private CheckBox mEnableAdpfWorkloadIncreaseBox; private CheckBox mHearWorkloadBox; private CheckBox mHighPerformanceAudioBox; + private CheckBox mDisableAdpfDurationBox; private Button mStartButton; private Button mStopButton; @@ -81,6 +82,7 @@ protected void onCreate(Bundle savedInstanceState) { mEnableAdpfWorkloadIncreaseBox = findViewById(R.id.enable_adpf_workload_increase); mHearWorkloadBox = findViewById(R.id.hear_workload); mHighPerformanceAudioBox = findViewById(R.id.high_performance_audio); + mDisableAdpfDurationBox = findViewById(R.id.disable_adpf_duration); mStartButton = findViewById(R.id.button_start_test); mStopButton = findViewById(R.id.button_stop_test); @@ -110,10 +112,11 @@ public void startTest(View view) { boolean adpfWorkloadIncreaseEnabled = mEnableAdpfWorkloadIncreaseBox.isChecked(); boolean hearWorkload = mHearWorkloadBox.isChecked(); boolean highPerformanceAudio = mHighPerformanceAudioBox.isChecked(); - + boolean reportActualDurationEnabled = !mDisableAdpfDurationBox.isChecked(); int result = start(targetDurationMs, numBursts, numVoices, alternateNumVoices, - alternatingPeriodMs, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio); + alternatingPeriodMs, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, + highPerformanceAudio, reportActualDurationEnabled); if (result != OPERATION_SUCCESS) { showErrorToast("start failed! Error:" + result); return; @@ -149,6 +152,7 @@ public void enableParamsUI(boolean enabled) { mEnableAdpfWorkloadIncreaseBox.setEnabled(enabled); mHearWorkloadBox.setEnabled(enabled); mHighPerformanceAudioBox.setEnabled(enabled); + mDisableAdpfDurationBox.setEnabled(enabled); } private void updateResultTextView() { @@ -166,7 +170,8 @@ private void updateResultTextView() { public native int start(int targetDurationMs, int numBursts, int numVoices, int alternateNumVoices, int alternatingPeriodMs, boolean adpfEnabled, boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload, - boolean highPerformanceAudio); + boolean highPerformanceAudio, + boolean reportActualDurationEnabled); public native boolean stopIfDone(); public native String getStatus(); public native int stop(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java index 2be32e7ed..ca6420a03 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java @@ -82,6 +82,7 @@ public class DynamicWorkloadActivity extends TestOutputActivityBase { private CheckBox mPerfHintBox; private CheckBox mWorkloadReportBox; private CheckBox mHighPerformanceAudioBox; + private CheckBox mDisableAdpfDurationBox; private boolean mDrawChartAlways = true; private CheckBox mDrawAlwaysBox; private CheckBox mSustainedPerformanceModeBox; @@ -332,6 +333,13 @@ public void onClick(View view) { }); mUseAltAdpfBox.setVisibility(View.GONE); + mDisableAdpfDurationBox = (CheckBox) findViewById(R.id.disable_adpf_duration); + mDisableAdpfDurationBox.setOnClickListener(buttonView -> { + CheckBox checkBox = (CheckBox) buttonView; + NativeEngine.setReportActualDurationEnabled(!checkBox.isChecked()); + }); + NativeEngine.setReportActualDurationEnabled(!mDisableAdpfDurationBox.isChecked()); + mPerfHintBox.setOnClickListener(buttonView -> { CheckBox checkBox = (CheckBox) buttonView; mShouldUseADPF = checkBox.isChecked(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java index 588dca4a5..6ce98dc39 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java @@ -19,4 +19,6 @@ public class NativeEngine { static native void setWorkloadReportingEnabled(boolean enabled); static native void setNotifyWorkloadIncreaseEnabled(boolean enabled); + + static native void setReportActualDurationEnabled(boolean enabled); } diff --git a/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml b/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml index 0c84787da..61c0bc69d 100644 --- a/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml +++ b/apps/OboeTester/app/src/main/res/layout/activity_audio_workload_test.xml @@ -157,6 +157,25 @@ android:text="High Performance Audio" /> + + + + + + + + + + + + + + lock(mLock); if (mHintSession != nullptr) { diff --git a/src/common/AdpfWrapper.h b/src/common/AdpfWrapper.h index bd5bcc02f..9abaf3bdc 100644 --- a/src/common/AdpfWrapper.h +++ b/src/common/AdpfWrapper.h @@ -72,6 +72,12 @@ namespace oboe { sUseAlternativeHack = enabled; } + /** + * Control whether the actual duration reporting to ADPF is disabled. + * @param disabled set true to disable reporting; false to enable. + */ + void setReportActualDurationDisabled(bool disabled); + /** * Return true if the platform reports support for the high-performance-audio * feature (APerfHintFeature::APERF_HINT_HIGH_PERFORMANCE_AUDIO). @@ -177,6 +183,7 @@ namespace oboe { APerformanceHintSession *mHintSession = nullptr; int64_t mBeginCallbackNanos = 0; static bool sUseAlternativeHack; + bool mIsReportActualDurationDisabled = false; int32_t mPreviousWorkload = 0; double mNanosPerWorkloadUnit = 0.0; }; From 57281c6a6b4b7fc63849f1eea0c1a4232dbab420 Mon Sep 17 00:00:00 2001 From: Robert Wu <85952307+robertwu1@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:45:41 -0800 Subject: [PATCH 4/6] address comments --- .../app/src/main/cpp/NativeAudioContext.h | 4 +- .../app/src/main/cpp/cpu/AudioWorkloadTest.h | 10 ++--- .../main/cpp/cpu/AudioWorkloadTestRunner.h | 40 +++++++++---------- .../app/src/main/cpp/jni-bridge.cpp | 21 ++++------ .../oboetester/AudioWorkloadTestActivity.java | 6 +-- .../AudioWorkloadTestRunnerActivity.java | 6 +-- .../oboetester/DynamicWorkloadActivity.java | 34 +++++++++------- .../com/mobileer/oboetester/NativeEngine.java | 2 +- apps/OboeTester/docs/AutomatedTesting.md | 1 + include/oboe/AudioStream.h | 4 +- src/aaudio/AudioStreamAAudio.h | 5 +-- 11 files changed, 65 insertions(+), 68 deletions(-) diff --git a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h index 0cfc88573..d58541f9b 100644 --- a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h +++ b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h @@ -341,10 +341,10 @@ class ActivityContext { oboeCallbackProxy->setNotifyWorkloadIncreaseEnabled(enabled); } - void setReportActualDurationEnabled(bool enabled) { + void setReportActualDurationDisabled(bool disabled) { std::shared_ptr stream = getOutputStream(); if (stream) { - stream->setReportActualDurationEnabled(enabled); + stream->setReportActualDurationDisabled(disabled); } } diff --git a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h index bc545f48a..89f1b125f 100644 --- a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h +++ b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTest.h @@ -99,7 +99,7 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { } // Apply the current setting for reporting actual duration once the stream exists. - mStream->setReportActualDurationEnabled(mReportActualDurationEnabled); + mStream->setReportActualDurationDisabled(mReportActualDurationDisabled); mFramesPerBurst = mStream->getFramesPerBurst(); mSampleRate = mStream->getSampleRate(); @@ -153,7 +153,7 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { int32_t start(int32_t targetDurationMillis, int32_t numBursts, int32_t numVoices, int32_t alternateNumVoices, int32_t alternatingPeriodMs, bool adpfEnabled, bool adpfWorkloadIncreaseEnabled, bool hearWorkload, bool highPerformanceAudio, - bool reportActualDurationEnabled) { + bool reportActualDurationDisabled) { std::lock_guard lock(mStreamLock); if (!mStream) { LOGE("Error: Stream not open."); @@ -179,9 +179,9 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { mRunning = true; mHearWorkload = hearWorkload; mAdpfWorkloadIncreaseEnabled = adpfWorkloadIncreaseEnabled; - mReportActualDurationEnabled = reportActualDurationEnabled; + mReportActualDurationDisabled = reportActualDurationDisabled; mStream->setPerformanceHintEnabled(adpfEnabled); - mStream->setReportActualDurationEnabled(mReportActualDurationEnabled); + mStream->setReportActualDurationDisabled(mReportActualDurationDisabled); // Apply performance hint configuration if requested via runner flags. oboe::PerformanceHintConfig cfg; cfg.highPerformanceAudio = highPerformanceAudio; @@ -432,7 +432,7 @@ class AudioWorkloadTest : oboe::AudioStreamDataCallback { std::atomic mStartTimeMs{0}; std::atomic mHearWorkload{false}; std::atomic mAdpfWorkloadIncreaseEnabled{false}; - std::atomic mReportActualDurationEnabled{true}; + std::atomic mReportActualDurationDisabled{false}; // Lock to protect mCallbackStatistics std::mutex mStatisticsLock; diff --git a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h index 84bf2a5ca..10a32d420 100644 --- a/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h +++ b/apps/OboeTester/app/src/main/cpp/cpu/AudioWorkloadTestRunner.h @@ -67,16 +67,16 @@ class AudioWorkloadTestRunner { * stream). */ int32_t start( - int32_t targetDurationMs, - int32_t numBursts, - int32_t numVoices, - int32_t alternateNumVoices, - int32_t alternatingPeriodMs, - bool adpfEnabled, - bool adpfWorkloadIncreaseEnabled, - bool hearWorkload, - bool highPerformanceAudio, - bool reportActualDurationEnabled) { + int32_t targetDurationMs, + int32_t numBursts, + int32_t numVoices, + int32_t alternateNumVoices, + int32_t alternatingPeriodMs, + bool adpfEnabled, + bool adpfWorkloadIncreaseEnabled, + bool hearWorkload, + bool highPerformanceAudio, + bool reportActualDurationDisabled) { if (mIsRunning) { LOGE("Error: Test already running."); return -1; @@ -93,16 +93,16 @@ class AudioWorkloadTestRunner { mResult = 0; int32_t result = mAudioWorkloadTest.start( - targetDurationMs, - numBursts, - numVoices, - alternateNumVoices, - alternatingPeriodMs, - adpfEnabled, - adpfWorkloadIncreaseEnabled, - hearWorkload, - highPerformanceAudio, - reportActualDurationEnabled); + targetDurationMs, + numBursts, + numVoices, + alternateNumVoices, + alternatingPeriodMs, + adpfEnabled, + adpfWorkloadIncreaseEnabled, + hearWorkload, + highPerformanceAudio, + reportActualDurationDisabled); if (result != static_cast(oboe::Result::OK)) { mResult = -1; diff --git a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp index af1017dec..511ad5a13 100644 --- a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp +++ b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp @@ -326,10 +326,10 @@ Java_com_mobileer_oboetester_TestAudioActivity_setUseAlternativeAdpf(JNIEnv *env } JNIEXPORT void JNICALL -Java_com_mobileer_oboetester_NativeEngine_setReportActualDurationEnabled(JNIEnv *env, +Java_com_mobileer_oboetester_NativeEngine_setReportActualDurationDisabled(JNIEnv *env, jclass type, jboolean enabled) { - engine.getCurrentActivity()->setReportActualDurationEnabled(enabled); + engine.getCurrentActivity()->setReportActualDurationDisabled(enabled); } JNIEXPORT jint JNICALL @@ -370,7 +370,7 @@ Java_com_mobileer_oboetester_OboeAudioStream_setPerformanceHintConfig( std::shared_ptr oboeStream = engine.getCurrentActivity()->getStream(streamIndex); if (oboeStream != nullptr) { oboe::PerformanceHintConfig cfg; - cfg.highPerformanceAudio = (highPerformance == JNI_TRUE); + cfg.highPerformanceAudio = highPerformance; oboeStream->setPerformanceHintConfig(cfg); } } @@ -1230,11 +1230,11 @@ Java_com_mobileer_oboetester_AudioWorkloadTestActivity_start(JNIEnv *env, jobjec jint targetDurationMs, jint numBursts, jint numVoices, jint numAlternateVoices, jint alternatingPeriodMs, jboolean adpfEnabled, jboolean adpfWorkloadIncreaseEnabled, jboolean hearWorkload, jboolean highPerformanceAudio, - jboolean reportActualDurationEnabled) { + jboolean reportActualDurationDisabled) { return sAudioWorkload.start(targetDurationMs, numBursts, numVoices, numAlternateVoices, alternatingPeriodMs, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio, - reportActualDurationEnabled); + reportActualDurationDisabled); } JNIEXPORT jint JNICALL @@ -1464,18 +1464,11 @@ Java_com_mobileer_oboetester_AudioWorkloadTestRunnerActivity_start(JNIEnv *env, jboolean adpfWorkloadIncreaseEnabled, jboolean hearWorkload, jboolean highPerformanceAudio, - jboolean reportActualDurationEnabled) { + jboolean reportActualDurationDisabled) { int32_t result = sAudioWorkloadRunner.start(targetDurationMs, numBursts, numVoices, alternateNumVoices, alternatingPeriodMillis, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, highPerformanceAudio, - reportActualDurationEnabled); - // When the runner starts, set performance hint config on the active stream - std::shared_ptr oboeStream = engine.getCurrentActivity()->getStream(0); - if (oboeStream != nullptr) { - oboe::PerformanceHintConfig cfg; - cfg.highPerformanceAudio = (highPerformanceAudio == JNI_TRUE); - oboeStream->setPerformanceHintConfig(cfg); - } + reportActualDurationDisabled); return result; } diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java index bb4bd9296..ef8413506 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestActivity.java @@ -226,13 +226,13 @@ public void openAudio(View view) { } public void startTest(View view) { - boolean reportActualDurationEnabled = !mDisableAdpfDurationBox.isChecked(); + boolean reportActualDurationDisabled = mDisableAdpfDurationBox.isChecked(); int result = start(mTargetDurationMsSlider.getValue(), mNumBurstsSlider.getValue(), mNumVoicesSlider.getValue(), mAlternateNumVoicesSlider.getValue(), mAlternatingPeriodMsSlider.getValue(), mEnableAdpfBox.isChecked(), mEnableAdpfWorkloadIncreaseBox.isChecked(), mHearWorkloadBox.isChecked(), - mHighPerformanceAudioBox.isChecked(), reportActualDurationEnabled); + mHighPerformanceAudioBox.isChecked(), reportActualDurationDisabled); if (result != OPERATION_SUCCESS) { showErrorToast("start failed! Error:" + result); return; @@ -342,7 +342,7 @@ public void updateStreamInfoView() { private native int start(int targetDurationMs, int numBursts, int numVoices, int numAlternateVoices, int alternatingPeriodMs, boolean adpfEnabled, boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload, - boolean highPerformanceAudio, boolean reportActualDurationEnabled); + boolean highPerformanceAudio, boolean reportActualDurationDisabled); private native int getCpuCount(); private native int setCpuAffinityForCallback(int mask); private native int getXRunCount(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java index 4ed127a06..ba13f1e00 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/AudioWorkloadTestRunnerActivity.java @@ -112,11 +112,11 @@ public void startTest(View view) { boolean adpfWorkloadIncreaseEnabled = mEnableAdpfWorkloadIncreaseBox.isChecked(); boolean hearWorkload = mHearWorkloadBox.isChecked(); boolean highPerformanceAudio = mHighPerformanceAudioBox.isChecked(); - boolean reportActualDurationEnabled = !mDisableAdpfDurationBox.isChecked(); + boolean reportActualDurationDisabled = mDisableAdpfDurationBox.isChecked(); int result = start(targetDurationMs, numBursts, numVoices, alternateNumVoices, alternatingPeriodMs, adpfEnabled, adpfWorkloadIncreaseEnabled, hearWorkload, - highPerformanceAudio, reportActualDurationEnabled); + highPerformanceAudio, reportActualDurationDisabled); if (result != OPERATION_SUCCESS) { showErrorToast("start failed! Error:" + result); return; @@ -171,7 +171,7 @@ public native int start(int targetDurationMs, int numBursts, int numVoices, int alternateNumVoices, int alternatingPeriodMs, boolean adpfEnabled, boolean adpfWorkloadIncreaseEnabled, boolean hearWorkload, boolean highPerformanceAudio, - boolean reportActualDurationEnabled); + boolean reportActualDurationDisabled); public native boolean stopIfDone(); public native String getStatus(); public native int stop(); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java index ca6420a03..eb9ea45d9 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/DynamicWorkloadActivity.java @@ -65,8 +65,10 @@ public class DynamicWorkloadActivity extends TestOutputActivityBase { public static final boolean VALUE_DEFAULT_SCROLL_GRAPHICS = false; public static final String KEY_USE_WORKLOAD_INCREASE_API = "use_workload_increase_api"; public static final boolean VALUE_DEFAULT_USE_WORKLOAD_INCREASE_API = false; - public static final String KEY_HIGH_PERFORMANCE_AUDIO = "high_performance_audio"; - public static final boolean VALUE_DEFAULT_HIGH_PERFORMANCE_AUDIO = false; + public static final String KEY_USE_HIGH_PERFORMANCE_AUDIO = "use_high_performance_audio"; + public static final boolean VALUE_DEFAULT_USE_HIGH_PERFORMANCE_AUDIO = false; + public static final String KEY_DISABLE_ADPF_DURATION = "disable_adpf_duration"; + public static final boolean VALUE_DEFAULT_DISABLE_ADPF_DURATION = false; private Button mStopButton; private Button mStartButton; @@ -93,6 +95,7 @@ public class DynamicWorkloadActivity extends TestOutputActivityBase { private boolean mEnableWorkloadIncreaseApi; private int mLastNotifyWorkloadResult; private boolean mShouldUseHighPerformanceAudio; + private boolean mDisableAdpfDuration; private static final int WORKLOAD_LOW = 1; private int mWorkloadHigh; // this will get set later @@ -319,7 +322,7 @@ public void onClick(View view) { // If the platform does not support the high-performance-audio APERF feature, // hide or disable the UI control so users don't attempt to enable it. boolean hpSupported = NativeEngine.isHighPerformanceAudioSupported(); - if (!hpSupported && mHighPerformanceAudioBox != null) { + if (!hpSupported) { mHighPerformanceAudioBox.setEnabled(false); mHighPerformanceAudioBox.setVisibility(View.GONE); } @@ -336,9 +339,9 @@ public void onClick(View view) { mDisableAdpfDurationBox = (CheckBox) findViewById(R.id.disable_adpf_duration); mDisableAdpfDurationBox.setOnClickListener(buttonView -> { CheckBox checkBox = (CheckBox) buttonView; - NativeEngine.setReportActualDurationEnabled(!checkBox.isChecked()); + NativeEngine.setReportActualDurationDisabled(checkBox.isChecked()); }); - NativeEngine.setReportActualDurationEnabled(!mDisableAdpfDurationBox.isChecked()); + NativeEngine.setReportActualDurationDisabled(mDisableAdpfDurationBox.isChecked()); mPerfHintBox.setOnClickListener(buttonView -> { CheckBox checkBox = (CheckBox) buttonView; @@ -347,6 +350,7 @@ public void onClick(View view) { mUseAltAdpfBox.setEnabled(!mShouldUseADPF); mWorkloadReportBox.setEnabled(mShouldUseADPF); mWorkloadIncreaseApiBox.setEnabled(mShouldUseADPF); + mHighPerformanceAudioBox.setEnabled(!mShouldUseADPF); }); mWorkloadReportBox.setOnClickListener(buttonView -> { @@ -364,12 +368,10 @@ public void onClick(View view) { }); mWorkloadIncreaseApiBox.setEnabled(mEnableWorkloadIncreaseApi); - if (mHighPerformanceAudioBox != null) { - mHighPerformanceAudioBox.setOnClickListener(buttonView -> { - CheckBox checkBox = (CheckBox) buttonView; - mAudioOutTester.getCurrentAudioStream().setPerformanceHintConfig(checkBox.isChecked()); - }); - } + mHighPerformanceAudioBox.setOnClickListener(buttonView -> { + CheckBox checkBox = (CheckBox) buttonView; + mAudioOutTester.getCurrentAudioStream().setPerformanceHintConfig(checkBox.isChecked()); + }); CheckBox hearWorkloadBox = (CheckBox) findViewById(R.id.hear_workload); hearWorkloadBox.setOnClickListener(buttonView -> { @@ -438,7 +440,6 @@ private void updateButtons(boolean running) { mStartButton.setEnabled(!running); mStopButton.setEnabled(running); mPerfHintBox.setEnabled(running); - mHighPerformanceAudioBox.setEnabled(running); mWorkloadReportBox.setEnabled(running && mShouldUseADPF); mWorkloadIncreaseApiBox.setEnabled(running && mShouldUseADPF); } @@ -514,9 +515,10 @@ public void startTestUsingBundle() { VALUE_DEFAULT_SCROLL_GRAPHICS); mEnableWorkloadIncreaseApi = mBundleFromIntent.getBoolean(KEY_USE_WORKLOAD_INCREASE_API, VALUE_DEFAULT_USE_WORKLOAD_INCREASE_API); - mShouldUseHighPerformanceAudio = mBundleFromIntent.getBoolean(KEY_HIGH_PERFORMANCE_AUDIO, - VALUE_DEFAULT_HIGH_PERFORMANCE_AUDIO); - + mShouldUseHighPerformanceAudio = mBundleFromIntent.getBoolean(KEY_USE_HIGH_PERFORMANCE_AUDIO, + VALUE_DEFAULT_USE_HIGH_PERFORMANCE_AUDIO); + mDisableAdpfDuration = mBundleFromIntent.getBoolean(KEY_DISABLE_ADPF_DURATION, + VALUE_DEFAULT_DISABLE_ADPF_DURATION); startTest(); runOnUiThread(() -> { @@ -529,6 +531,8 @@ public void startTestUsingBundle() { mWorkloadIncreaseApiBox.setChecked(mEnableWorkloadIncreaseApi); setNotifyWorkloadIncreaseEnabled(mEnableWorkloadIncreaseApi); mDrawAlwaysBox.setChecked(mDrawChartAlways); + mDisableAdpfDurationBox.setChecked(mDisableAdpfDuration); + NativeEngine.setReportActualDurationDisabled(mDisableAdpfDuration); }); diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java index 6ce98dc39..58aec8417 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java @@ -20,5 +20,5 @@ public class NativeEngine { static native void setNotifyWorkloadIncreaseEnabled(boolean enabled); - static native void setReportActualDurationEnabled(boolean enabled); + static native void setReportActualDurationDisabled(boolean enabled); } diff --git a/apps/OboeTester/docs/AutomatedTesting.md b/apps/OboeTester/docs/AutomatedTesting.md index e5e315467..c14bfd5b5 100644 --- a/apps/OboeTester/docs/AutomatedTesting.md +++ b/apps/OboeTester/docs/AutomatedTesting.md @@ -145,6 +145,7 @@ There are some optional parameters for just the "cpu_load" test: --ez scroll_graphics {true, false} // if true then continually update the power scope. Default is false. --ez use_workload_increase_api {true, false} // if true and using ADPF, notify adpf with workload increase/reset apis. Default is false. --ez use_high_performance_audio {true, false} // if true, request highPerformanceAudio in the performance hint session creation config. Default is false. + --ez disable_adpf_duration {true, false} // if true, disable updating the actual adpf duration per callback. Default is false. For example, a complete command for a "latency" test might be: diff --git a/include/oboe/AudioStream.h b/include/oboe/AudioStream.h index c7346263d..58259741b 100644 --- a/include/oboe/AudioStream.h +++ b/include/oboe/AudioStream.h @@ -577,9 +577,9 @@ class AudioStream : public AudioStreamBase { /** * Control whether the actual duration is reported to ADPF. * This only affects AAudio streams. By default, it is enabled. - * @param enabled true to enable reporting actual duration to ADPF + * @param disabled true to disable reporting actual duration to ADPF */ - virtual void setReportActualDurationEnabled([[maybe_unused]] bool enabled) {} + virtual void setReportActualDurationDisabled([[maybe_unused]] bool disabled) {} /** * This only tells you if the feature has been requested. diff --git a/src/aaudio/AudioStreamAAudio.h b/src/aaudio/AudioStreamAAudio.h index d5d4803ec..60ba17f23 100644 --- a/src/aaudio/AudioStreamAAudio.h +++ b/src/aaudio/AudioStreamAAudio.h @@ -100,9 +100,8 @@ class AudioStreamAAudio : public AudioStream { mAdpfOpenAttempted = false; } - void setReportActualDurationEnabled(bool enabled) override { - // Public API expects 'enabled'; internally we manage a 'disabled' flag. - mAdpfWrapper.setReportActualDurationDisabled(!enabled); + void setReportActualDurationDisabled(bool disabled) override { + mAdpfWrapper.setReportActualDurationDisabled(disabled); } oboe::Result reportWorkload(int32_t appWorkload) override { From b32b9d7c4595fe990a09e3bce81b76744008828c Mon Sep 17 00:00:00 2001 From: Robert Wu <85952307+robertwu1@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:00:39 -0800 Subject: [PATCH 5/6] add tracing to Oboe callbacks --- src/common/AudioStream.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/common/AudioStream.cpp b/src/common/AudioStream.cpp index b3f7e26e8..6dc4f89d0 100644 --- a/src/common/AudioStream.cpp +++ b/src/common/AudioStream.cpp @@ -25,6 +25,7 @@ #include "oboe/Utilities.h" #include "OboeDebug.h" +#include "Trace.h" namespace oboe { @@ -70,6 +71,10 @@ DataCallbackResult AudioStream::fireDataCallback(void *audioData, int32_t numFra beginPerformanceHintInCallback(); + if (Trace::getInstance().isEnabled()) { + Trace::getInstance().beginSection("OboeCallback"); + } + // Call the app to do the work. DataCallbackResult result; if (mDataCallback) { @@ -77,6 +82,11 @@ DataCallbackResult AudioStream::fireDataCallback(void *audioData, int32_t numFra } else { result = onDefaultCallback(audioData, numFrames); } + + if (Trace::getInstance().isEnabled()) { + Trace::getInstance().endSection(); + } + // On Oreo, we might get called after returning stop. // So block that here. setDataCallbackEnabled(result == DataCallbackResult::Continue); @@ -94,6 +104,10 @@ int32_t AudioStream::firePartialDataCallback(void *audioData, int numFrames) { beginPerformanceHintInCallback(); + if (Trace::getInstance().isEnabled()) { + Trace::getInstance().beginSection("PartialOboeCallback"); + } + // Call the app to do the work. int32_t result; if (mPartialDataCallback) { @@ -103,6 +117,10 @@ int32_t AudioStream::firePartialDataCallback(void *audioData, int numFrames) { result = -1; // This should not happen, return negative value to stop the stream. } + if (Trace::getInstance().isEnabled()) { + Trace::getInstance().endSection(); + } + endPerformanceHintInCallback(numFrames); return result; From ac6b33d1777e1cbac3458ef9cd7902ef7c2a9e73 Mon Sep 17 00:00:00 2001 From: Robert Wu <85952307+robertwu1@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:59:27 -0800 Subject: [PATCH 6/6] address comments --- apps/OboeTester/app/src/main/cpp/jni-bridge.cpp | 4 ++-- .../src/main/java/com/mobileer/oboetester/NativeEngine.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp index 511ad5a13..1b68f7b7e 100644 --- a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp +++ b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp @@ -328,8 +328,8 @@ Java_com_mobileer_oboetester_TestAudioActivity_setUseAlternativeAdpf(JNIEnv *env JNIEXPORT void JNICALL Java_com_mobileer_oboetester_NativeEngine_setReportActualDurationDisabled(JNIEnv *env, jclass type, - jboolean enabled) { - engine.getCurrentActivity()->setReportActualDurationDisabled(enabled); + jboolean disabled) { + engine.getCurrentActivity()->setReportActualDurationDisabled(disabled); } JNIEXPORT jint JNICALL diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java index 58aec8417..fa82fcfc6 100644 --- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java +++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/NativeEngine.java @@ -20,5 +20,5 @@ public class NativeEngine { static native void setNotifyWorkloadIncreaseEnabled(boolean enabled); - static native void setReportActualDurationDisabled(boolean enabled); + static native void setReportActualDurationDisabled(boolean disabled); }