audio: Refactor configuration population
In 'Module::setAudioPortConfig' allow subclasses to provide
their own suggested configuration.
In 'Module::populateConnectedDevicePort' provide the ID of
the device port instance that will be created as a result
of connecting an external device.
Also, expose 'ModuleDebug' flags to subclasses so that they
can know when device connections are simulated.
Bug: 264712385
Test: atest VtsHalAudioCoreTargetTest
Change-Id: Iceb2bdeb61c3470554b592fe197efa54d3b9e578
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 6c4d7ac..b8e1df8 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -93,32 +93,6 @@
return std::all_of(profiles.begin(), profiles.end(), isDynamicProfile);
}
-// Note: does not assign an ID to the config.
-bool generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
- const bool allowDynamicConfig = port.ext.getTag() == AudioPortExt::device;
- *config = {};
- config->portId = port.id;
- for (const auto& profile : port.profiles) {
- if (isDynamicProfile(profile)) continue;
- config->format = profile.format;
- config->channelMask = *profile.channelMasks.begin();
- config->sampleRate = Int{.value = *profile.sampleRates.begin()};
- config->flags = port.flags;
- config->ext = port.ext;
- return true;
- }
- if (allowDynamicConfig) {
- config->format = AudioFormatDescription{};
- config->channelMask = AudioChannelLayout{};
- config->sampleRate = Int{.value = 0};
- config->flags = port.flags;
- config->ext = port.ext;
- return true;
- }
- LOG(ERROR) << __func__ << ": port " << port.id << " only has dynamic profiles";
- return false;
-}
-
bool findAudioProfile(const AudioPort& port, const AudioFormatDescription& format,
AudioProfile* profile) {
if (auto profilesIt =
@@ -204,10 +178,11 @@
}
auto& configs = getConfig().portConfigs;
auto portConfigIt = findById<AudioPortConfig>(configs, in_portConfigId);
+ const int32_t nominalLatencyMs = getNominalLatencyMs(*portConfigIt);
// Since this is a private method, it is assumed that
// validity of the portConfigId has already been checked.
- const int32_t minimumStreamBufferSizeFrames = calculateBufferSizeFrames(
- getNominalLatencyMs(*portConfigIt), portConfigIt->sampleRate.value().value);
+ const int32_t minimumStreamBufferSizeFrames =
+ calculateBufferSizeFrames(nominalLatencyMs, portConfigIt->sampleRate.value().value);
if (in_bufferSizeFrames < minimumStreamBufferSizeFrames) {
LOG(ERROR) << __func__ << ": insufficient buffer size " << in_bufferSizeFrames
<< ", must be at least " << minimumStreamBufferSizeFrames;
@@ -241,7 +216,7 @@
std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
portConfigIt->format.value(), portConfigIt->channelMask.value(),
- portConfigIt->sampleRate.value().value, flags, getNominalLatencyMs(*portConfigIt),
+ portConfigIt->sampleRate.value().value, flags, nominalLatencyMs,
portConfigIt->ext.get<AudioPortExt::mix>().handle,
std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
asyncCallback, outEventCallback,
@@ -328,6 +303,29 @@
return ndk::ScopedAStatus::ok();
}
+bool Module::generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
+ const bool allowDynamicConfig = port.ext.getTag() == AudioPortExt::device;
+ for (const auto& profile : port.profiles) {
+ if (isDynamicProfile(profile)) continue;
+ config->format = profile.format;
+ config->channelMask = *profile.channelMasks.begin();
+ config->sampleRate = Int{.value = *profile.sampleRates.begin()};
+ config->flags = port.flags;
+ config->ext = port.ext;
+ return true;
+ }
+ if (allowDynamicConfig) {
+ config->format = AudioFormatDescription{};
+ config->channelMask = AudioChannelLayout{};
+ config->sampleRate = Int{.value = 0};
+ config->flags = port.flags;
+ config->ext = port.ext;
+ return true;
+ }
+ LOG(ERROR) << __func__ << ": port " << port.id << " only has dynamic profiles";
+ return false;
+}
+
void Module::populateConnectedProfiles() {
Configuration& config = getConfig();
for (const AudioPort& port : config.ports) {
@@ -617,10 +615,11 @@
std::vector<AudioRoute*> routesToMixPorts = getAudioRoutesForAudioPortImpl(templateId);
std::set<int32_t> routableMixPortIds = getRoutableAudioPortIds(templateId, &routesToMixPorts);
+ const int32_t nextPortId = getConfig().nextPortId++;
if (!mDebug.simulateDeviceConnections) {
// Even if the device port has static profiles, the HAL module might need to update
// them, or abort the connection process.
- RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
+ RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort, nextPortId));
} else if (hasDynamicProfilesOnly(connectedPort.profiles)) {
auto& connectedProfiles = getConfig().connectedProfiles;
if (auto connectedProfilesIt = connectedProfiles.find(templateId);
@@ -644,7 +643,7 @@
}
}
- connectedPort.id = getConfig().nextPortId++;
+ connectedPort.id = nextPortId;
auto [connectedPortsIt, _] =
mConnectedDevicePorts.insert(std::pair(connectedPort.id, std::set<int32_t>()));
LOG(DEBUG) << __func__ << ": template port " << templateId << " external device connected, "
@@ -1035,6 +1034,18 @@
ndk::ScopedAStatus Module::setAudioPortConfig(const AudioPortConfig& in_requested,
AudioPortConfig* out_suggested, bool* _aidl_return) {
+ auto generate = [this](const AudioPort& port, AudioPortConfig* config) {
+ return generateDefaultPortConfig(port, config);
+ };
+ return setAudioPortConfigImpl(in_requested, generate, out_suggested, _aidl_return);
+}
+
+ndk::ScopedAStatus Module::setAudioPortConfigImpl(
+ const AudioPortConfig& in_requested,
+ const std::function<bool(const ::aidl::android::media::audio::common::AudioPort& port,
+ ::aidl::android::media::audio::common::AudioPortConfig* config)>&
+ fillPortConfig,
+ AudioPortConfig* out_suggested, bool* applied) {
LOG(DEBUG) << __func__ << ": requested " << in_requested.toString();
auto& configs = getConfig().portConfigs;
auto existing = configs.end();
@@ -1063,7 +1074,8 @@
*out_suggested = *existing;
} else {
AudioPortConfig newConfig;
- if (generateDefaultPortConfig(*portIt, &newConfig)) {
+ newConfig.portId = portIt->id;
+ if (fillPortConfig(*portIt, &newConfig)) {
*out_suggested = newConfig;
} else {
LOG(ERROR) << __func__ << ": unable generate a default config for port " << portId;
@@ -1168,17 +1180,17 @@
if (existing == configs.end() && requestedIsValid && requestedIsFullySpecified) {
out_suggested->id = getConfig().nextPortId++;
configs.push_back(*out_suggested);
- *_aidl_return = true;
+ *applied = true;
LOG(DEBUG) << __func__ << ": created new port config " << out_suggested->toString();
} else if (existing != configs.end() && requestedIsValid) {
*existing = *out_suggested;
- *_aidl_return = true;
+ *applied = true;
LOG(DEBUG) << __func__ << ": updated port config " << out_suggested->toString();
} else {
LOG(DEBUG) << __func__ << ": not applied; existing config ? " << (existing != configs.end())
<< "; requested is valid? " << requestedIsValid << ", fully specified? "
<< requestedIsFullySpecified;
- *_aidl_return = false;
+ *applied = false;
}
return ndk::ScopedAStatus::ok();
}
@@ -1530,7 +1542,7 @@
return mIsMmapSupported.value();
}
-ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort) {
+ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort, int32_t) {
if (audioPort->ext.getTag() != AudioPortExt::device) {
LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);