audio: Clarify "mute" behavior for playback parameters
When the client specifies `TimestretchFallbackMode.MUTE`,
it should still be allowed for the HAL implementation
to return an error if parameters are out of range and
it does not support muted playback.
Bug: 381385909
Bug: 384626226
Test: atest VtsHalAudioCoreTargetTest
Change-Id: Ic4db99b54965c65186a46761776dd11b7437dfb1
diff --git a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
index f26dc1c..111969f 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
@@ -214,7 +214,8 @@
*
* The range of supported values for speed and pitch factors is provided by
* the 'IModule.getSupportedPlaybackRateFactors' method. Out of range speed
- * and pitch values must not be rejected if the fallback mode is 'MUTE'.
+ * and pitch values may result in silent playback instead of returning an
+ * error in the case when the fallback mode is 'MUTE'.
*
* @param playbackRate Playback parameters to set.
* @throws EX_ILLEGAL_ARGUMENT If provided parameters are out of acceptable range.
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 6bce107..93c2a61 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -376,7 +376,8 @@
template <typename PropType, class Instance, typename Getter, typename Setter>
void TestAccessors(Instance* inst, Getter getter, Setter setter,
const std::vector<PropType>& validValues,
- const std::vector<PropType>& invalidValues, bool* isSupported) {
+ const std::vector<PropType>& invalidValues, bool* isSupported,
+ const std::vector<PropType>* ambivalentValues = nullptr) {
PropType initialValue{};
ScopedAStatus status = (inst->*getter)(&initialValue);
if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
@@ -395,6 +396,15 @@
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v))
<< "for an invalid value: " << ::testing::PrintToString(v);
}
+ if (ambivalentValues != nullptr) {
+ for (const auto v : *ambivalentValues) {
+ const auto status = (inst->*setter)(v);
+ if (!status.isOk()) {
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, status)
+ << "for an ambivalent value: " << ::testing::PrintToString(v);
+ }
+ }
+ }
EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
}
@@ -3936,11 +3946,6 @@
AudioPlaybackRate{1.0f, 1.0f, tsVoice, fbFail},
AudioPlaybackRate{factors.maxSpeed, factors.maxPitch, tsVoice, fbMute},
AudioPlaybackRate{factors.minSpeed, factors.minPitch, tsVoice, fbMute},
- // Out of range speed / pitch values must not be rejected if the fallback mode is "mute"
- AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsDefault, fbMute},
- AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsDefault, fbMute},
- AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsVoice, fbMute},
- AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsVoice, fbMute},
};
const std::vector<AudioPlaybackRate> invalidValues = {
AudioPlaybackRate{factors.maxSpeed, factors.maxPitch * 2, tsDefault, fbFail},
@@ -3956,6 +3961,14 @@
AudioPlaybackRate{1.0f, 1.0f, tsDefault,
AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT},
};
+ const std::vector<AudioPlaybackRate> ambivalentValues = {
+ // Out of range speed / pitch values may optionally be rejected if the fallback mode
+ // is "mute".
+ AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsDefault, fbMute},
+ AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsDefault, fbMute},
+ AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsVoice, fbMute},
+ AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsVoice, fbMute},
+ };
bool atLeastOneSupports = false;
for (const auto& port : offloadMixPorts) {
const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
@@ -3965,7 +3978,8 @@
bool isSupported = false;
EXPECT_NO_FATAL_FAILURE(TestAccessors<AudioPlaybackRate>(
stream.get(), &IStreamOut::getPlaybackRateParameters,
- &IStreamOut::setPlaybackRateParameters, validValues, invalidValues, &isSupported));
+ &IStreamOut::setPlaybackRateParameters, validValues, invalidValues, &isSupported,
+ &ambivalentValues));
if (isSupported) atLeastOneSupports = true;
}
if (!atLeastOneSupports) {