audio policy: select output with best sample format match
Add rules allowing selection of the output stream with the sample
format offering the best match to the client track sample format
when more than one output is compatible with a request.
Bug: 27210844
Change-Id: I31981940be5d1c06d713d52187cfb0a7bf355773
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index e3ee4e5..18acb23 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -126,3 +126,18 @@
}
return 0;
}
+
+/* Indicates if audio formats are equivalent when considering a match between
+ * audio HAL supported formats and client requested formats
+ */
+static inline bool audio_formats_match(audio_format_t format1,
+ audio_format_t format2)
+{
+ if (audio_is_linear_pcm(format1) &&
+ (audio_bytes_per_sample(format1) > 2) &&
+ audio_is_linear_pcm(format2) &&
+ (audio_bytes_per_sample(format2) > 2)) {
+ return true;
+ }
+ return format1 == format2;
+}
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 0da3aea..e19a8ee 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -110,6 +110,12 @@
static int compareFormats(audio_format_t format1, audio_format_t format2);
+ // Used to select an audio HAL output stream with a sample format providing the
+ // less degradation for a given AudioTrack sample format.
+ static bool isBetterFormatMatch(audio_format_t newFormat,
+ audio_format_t currentFormat,
+ audio_format_t targetFormat);
+
audio_module_handle_t getModuleHandle() const;
uint32_t getModuleVersion() const;
const char *getModuleName() const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 191439e..bda59ad 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -268,6 +268,32 @@
return index1 - index2;
}
+bool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
+ audio_format_t currentFormat,
+ audio_format_t targetFormat)
+{
+ if (newFormat == currentFormat) {
+ return false;
+ }
+ if (currentFormat == AUDIO_FORMAT_INVALID) {
+ return true;
+ }
+ if (newFormat == targetFormat) {
+ return true;
+ }
+ int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
+ audio_bytes_per_sample(currentFormat);
+ int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
+ audio_bytes_per_sample(newFormat);
+
+ if (abs(newDiffBytes) < abs(currentDiffBytes)) {
+ return true;
+ } else if (abs(newDiffBytes) == abs(currentDiffBytes)) {
+ return (newDiffBytes >= 0);
+ }
+ return false;
+}
+
void AudioPort::pickAudioProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format) const
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
index c599665..961072e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
@@ -31,7 +31,7 @@
status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask,
audio_format_t format) const
{
- if (format == mFormat &&
+ if (audio_formats_match(format, mFormat) &&
(mChannelMasks.isEmpty() || supportsChannels(channelMask)) &&
(mSamplingRates.isEmpty() || supportsRate(samplingRate))) {
return NO_ERROR;