Fix matching device address using audio attributes.
The previous code works only with an assumption there's single tag
present (implicitly added one with device address).
Test: atest AudioServiceHostTest AudioHostTest AudioPolicyHostTest
Test: atest audiosystem_tests audiopolicy_tests
Bug: 244713292
Change-Id: I9a7241521fd7d9246275d1e4d77f6c3b06301163
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 7530132..54a143c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -134,4 +134,6 @@
audio_session_t session);
};
+std::optional<std::string> extractAddressFromAudioAttributes(const audio_attributes_t& attr);
+
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3b9a855..003dcaf 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -18,6 +18,9 @@
//#define LOG_NDEBUG 0
#include <algorithm>
+#include <iterator>
+#include <optional>
+#include <regex>
#include "AudioPolicyMix.h"
#include "TypeConverter.h"
#include "HwModule.h"
@@ -28,6 +31,11 @@
namespace android {
namespace {
+bool matchAddressToTags(const audio_attributes_t& attr, const String8& addr) {
+ std::optional<std::string> tagAddress = extractAddressFromAudioAttributes(attr);
+ return tagAddress.has_value() && tagAddress->compare(addr.c_str()) == 0;
+}
+
// Returns true if the criterion matches.
// The exclude criteria are handled in the same way as positive
// ones - only condition is matched (the function will return
@@ -332,24 +340,14 @@
}
// if there is an address match, prioritize that match
- if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
- strncmp(attributes.tags + strlen("addr="),
- mix->mDeviceAddress.string(),
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
- ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
- return true;
- }
-
- if (areMixCriteriaMatched(mix->mCriteria, attributes, uid, session)) {
- ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
- return true;
+ if (matchAddressToTags(attributes, mix->mDeviceAddress)
+ || areMixCriteriaMatched(mix->mCriteria, attributes, uid, session)) {
+ ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
+ return true;
}
} else if (mix->mMixType == MIX_TYPE_RECORDERS) {
if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
- strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
- strncmp(attributes.tags + strlen("addr="),
- mix->mDeviceAddress.string(),
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+ matchAddressToTags(attributes, mix->mDeviceAddress)) {
return true;
}
}
@@ -404,14 +402,14 @@
status_t AudioPolicyMixCollection::getInputMixForAttr(
audio_attributes_t attr, sp<AudioPolicyMix> *policyMix)
{
- if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) {
+ std::optional<std::string> address = extractAddressFromAudioAttributes(attr);
+ if (!address.has_value()) {
return BAD_VALUE;
}
- String8 address(attr.tags + strlen("addr="));
#ifdef LOG_NDEBUG
ALOGV("getInputMixForAttr looking for address %s for source %d\n mixes available:",
- address.string(), attr.source);
+ address->c_str(), attr.source);
for (size_t i = 0; i < size(); i++) {
const sp<AudioPolicyMix> audioPolicyMix = itemAt(i);
ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
@@ -421,20 +419,20 @@
size_t index;
for (index = 0; index < size(); index++) {
const sp<AudioPolicyMix>& registeredMix = itemAt(index);
- if (registeredMix->mDeviceAddress.compare(address) == 0) {
+ if (address->compare(registeredMix->mDeviceAddress.c_str()) == 0) {
ALOGD("getInputMixForAttr found addr=%s dev=0x%x",
registeredMix->mDeviceAddress.string(), registeredMix->mDeviceType);
break;
}
}
if (index == size()) {
- ALOGW("getInputMixForAttr() no policy for address %s", address.string());
+ ALOGW("getInputMixForAttr() no policy for address %s", address->c_str());
return BAD_VALUE;
}
const sp<AudioPolicyMix> audioPolicyMix = itemAt(index);
if (audioPolicyMix->mMixType != MIX_TYPE_PLAYERS) {
- ALOGW("getInputMixForAttr() bad policy mix type for address %s", address.string());
+ ALOGW("getInputMixForAttr() bad policy mix type for address %s", address->c_str());
return BAD_VALUE;
}
if (policyMix != nullptr) {
@@ -634,4 +632,14 @@
}
}
+std::optional<std::string> extractAddressFromAudioAttributes(const audio_attributes_t& attr) {
+ static const std::regex addrTagRegex("addr=([^;]+)");
+
+ std::cmatch match;
+ if (std::regex_search(attr.tags, match, addrTagRegex)) {
+ return match[1].str();
+ }
+ return std::nullopt;
+}
+
}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 199a1d5..5977bfd 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2504,7 +2504,7 @@
*inputType = API_INPUT_INVALID;
if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
- strncmp(attributes.tags, "addr=", strlen("addr=")) == 0) {
+ extractAddressFromAudioAttributes(attributes).has_value()) {
status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
if (status != NO_ERROR) {
ALOGW("%s could not find input mix for attr %s",
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index e1bf414..ba5b6b2 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1554,7 +1554,16 @@
.withTags("addr=remote_submix_media"),
DPTestParam(USAGE_MEDIA_ALARM_CRITERIA, /*expected_match=*/ true)
.withUsage(AUDIO_USAGE_ASSISTANT)
- .withTags("addr=remote_submix_media")));
+ .withTags("addr=remote_submix_media"),
+ DPTestParam(USAGE_MEDIA_ALARM_CRITERIA, /*expected_match=*/ true)
+ .withUsage(AUDIO_USAGE_ASSISTANT)
+ .withTags("sometag;addr=remote_submix_media;othertag=somevalue"),
+ DPTestParam(USAGE_MEDIA_ALARM_CRITERIA, /*expected_match=*/ true)
+ .withUsage(AUDIO_USAGE_ASSISTANT)
+ .withTags("addr=remote_submix_media;othertag"),
+ DPTestParam(USAGE_MEDIA_ALARM_CRITERIA, /*expected_match=*/ true)
+ .withUsage(AUDIO_USAGE_ASSISTANT)
+ .withTags("sometag;othertag;addr=remote_submix_media")));
static constexpr audio_session_t TEST_SESSION_ID = static_cast<audio_session_t>(42);
static constexpr audio_session_t OTHER_SESSION_ID = static_cast<audio_session_t>(77);