audiopolicy: Fix sofware bridge creation for AudioHAL supporting routing APIs
AudioPolicy roughly checks if HAL supports routing APIs 3.0 to enable or
not software bridge in case of device to device patch requests.
However, Audio HAL declares in XML file routes supported. AudioPolicy
shall refine its decision upon information available in the policy configuration
file.
Test: Audio smoke tests.
Test: CTS tests for AudioRecord, AudioTrack and AudioEffect
Change-Id: Idc2e1ccd7d9fb6385f9a05ee002bec045e608232
Signed-off-by: Francois Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
index 330f1d4..0357ff4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
@@ -46,6 +46,19 @@
audio_route_type_t getType() const { return mType; }
+ /**
+ * @brief supportsPatch checks if an audio patch is supported by a Route declared in
+ * the audio_policy_configuration.xml file.
+ * If the patch is supported natively by an AudioHAL (which supports of course Routing API 3.0),
+ * audiopolicy will not request AudioFlinger to use a software bridge to realize a patch
+ * between 2 ports.
+ * @param srcPort (aka the source) to be considered
+ * @param dstPort (aka the sink) to be considered
+ * @return true if the audio route supports the connection between the sink and the source,
+ * false otherwise
+ */
+ bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+
void dump(String8 *dst, int spaces) const;
private:
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 6560431..2b57fa9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -81,6 +81,17 @@
return mPorts.findByTagName(tagName);
}
+ /**
+ * @brief supportsPatch checks if an audio patch between 2 ports beloging to this HwModule
+ * is supported by a HwModule. The ports and the route shall be declared in the
+ * audio_policy_configuration.xml file.
+ * @param srcPort (aka the source) to be considered
+ * @param dstPort (aka the sink) to be considered
+ * @return true if the HwModule supports the connection between the sink and the source,
+ * false otherwise
+ */
+ bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+
// TODO remove from here (split serialization)
void dump(String8 *dst) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index c1fe5b0..79f0919 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -37,4 +37,19 @@
dst->append("\n");
}
+bool AudioRoute::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const
+{
+ if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
+ return false;
+ }
+ ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string());
+ for (const auto &sourcePort : mSources) {
+ if (sourcePort == srcPort) {
+ ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string());
+ return true;
+ }
+ }
+ return false;
+}
+
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 92bc595..59ba479 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -218,6 +218,15 @@
mHandle = handle;
}
+bool HwModule::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const {
+ for (const auto &route : mRoutes) {
+ if (route->supportsPatch(srcPort, dstPort)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void HwModule::dump(String8 *dst) const
{
dst->appendFormat(" - name: %s\n", getName());
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 02f6f5a..d13253d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3083,8 +3083,10 @@
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
// - audio HAL version is < 3.0
+ // - audio HAL version is >= 3.0 but no route has been declared between devices
if (!srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) ||
- (srcDeviceDesc->mModule->getHalVersionMajor() < 3)) {
+ (srcDeviceDesc->mModule->getHalVersionMajor() < 3) ||
+ !srcDeviceDesc->mModule->supportsPatch(srcDeviceDesc, sinkDeviceDesc)) {
// support only one sink device for now to simplify output selection logic
if (patch->num_sinks > 1) {
return INVALID_OPERATION;