Preempt direct track on resource constraint
If a direct output profile has reached its max open count, attempt to
close existing tracks on the profile to service the latest request.
Test: test_steal_exclusive
Test: atest AudioTrackOffloadTest
Test: atest ^#testMultipleAudioTrackOffloadPreemption
Bug: 294525897
Change-Id: If94405b5e92ae4c2e3ee8c97a3a941b3224940cd
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 58e0486..15b03cb 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2855,7 +2855,9 @@
if (isOffloadedOrDirect_l() || mDoNotReconnect) {
// FIXME re-creation of offloaded and direct tracks is not yet implemented;
- // reconsider enabling for linear PCM encodings when position can be preserved.
+ // Disabled since (1) timestamp correction is not implemented for non-PCM and
+ // (2) We pre-empt existing direct tracks on resource constraint, so these tracks
+ // shouldn't reconnect.
result = DEAD_OBJECT;
return result;
}
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index b4f71ae..6a37b4e 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -43,6 +43,8 @@
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"audioclient-types-aidl-cpp",
+ // Flag support
+ "com.android.media.audioserver-aconfig-cc"
],
header_libs: [
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2e13178..81369e2 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -42,6 +42,7 @@
#include <Serializer.h>
#include <android/media/audio/common/AudioPort.h>
#include <com_android_media_audio.h>
+#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
#include <cutils/properties.h>
#include <media/AudioParameter.h>
@@ -1509,11 +1510,30 @@
}
if (!profile->canOpenNewIo()) {
+ if (!com::android::media::audioserver::direct_track_reprioritization()) {
+ return NAME_NOT_FOUND;
+ } else if ((profile->getFlags() & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0) {
+ // MMAP gracefully handles lack of an exclusive track resource by mixing
+ // above the audio framework. For AAudio to know that the limit is reached,
+ // return an error.
+ return NAME_NOT_FOUND;
+ } else {
+ // Close outputs on this profile, if available, to free resources for this request
+ for (int i = 0; i < mOutputs.size() && !profile->canOpenNewIo(); i++) {
+ const auto desc = mOutputs.valueAt(i);
+ if (desc->mProfile == profile) {
+ closeOutput(desc->mIoHandle);
+ }
+ }
+ }
+ }
+
+ // Unable to close streams to find free resources for this request
+ if (!profile->canOpenNewIo()) {
return NAME_NOT_FOUND;
}
- sp<SwAudioOutputDescriptor> outputDesc =
- new SwAudioOutputDescriptor(profile, mpClientInterface);
+ auto outputDesc = sp<SwAudioOutputDescriptor>::make(profile, mpClientInterface);
// An MSD patch may be using the only output stream that can service this request. Release
// all MSD patches to prioritize this request over any active output on MSD.