APM: update logic of populating profiles for dynamic mix port.
For AIDL HAL, use getAudioPort API to query the profiles for the dynamic
mix ports.
For HIDL HAL, if the HAL supports getAudioPort API, add the profiles of
the device port that contain attributes also reported by getParameters
API. The attributes reported by getParameters API but not in device port
will also be added to mix port.
The reason of using getAudioPort API instead of getParameters is that
getAudioPort API can return well structed audio profiles, which show the
correct relationship between audio format and sample rates, channel
masks.
Test: repo steps from the bug
Test: atest audiofoundation_containers_test
Test: atest audiopolicy_tests
Bug: 284033428
Change-Id: I6d3faf49470514c05fe57be755bb868d74d74dbb
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 72fe32b..b7af103 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -836,6 +836,33 @@
return OK;
}
+status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
+ struct audio_port_v7 *mixPort) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (devicePort->type != AUDIO_PORT_TYPE_DEVICE) {
+ return BAD_VALUE;
+ }
+ if (mixPort->type != AUDIO_PORT_TYPE_MIX) {
+ return BAD_VALUE;
+ }
+ const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
+ auto it = findPortConfig(std::nullopt /*config*/, std::nullopt/*flags*/, aidlHandle);
+ if (it == mPortConfigs.end()) {
+ ALOGE("%s, cannot find mix port config for handle=%u", __func__, aidlHandle);
+ return BAD_VALUE;
+ }
+ AudioPort port;
+ if (status_t status = getAudioPort(it->second.portId, &port); status != NO_ERROR) {
+ return status;
+ }
+ const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
+ *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
+ port, isInput));
+ return NO_ERROR;
+}
+
status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
@@ -1702,7 +1729,9 @@
}
DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
- const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
+ const std::optional<AudioConfig>& config,
+ const std::optional<AudioIoFlags>& flags,
+ int32_t ioHandle) {
using Tag = AudioPortExt::Tag;
return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
[&](const auto& pair) {
@@ -1713,7 +1742,8 @@
"%s: stored mix port config is not fully specified: %s",
__func__, p.toString().c_str());
return p.ext.getTag() == Tag::mix &&
- isConfigEqualToPortConfig(config, p) &&
+ (!config.has_value() ||
+ isConfigEqualToPortConfig(config.value(), p)) &&
(!flags.has_value() || p.flags.value() == flags.value()) &&
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
@@ -1840,6 +1870,25 @@
return OK;
}
+status_t DeviceHalAidl::getAudioPort(int32_t portId, AudioPort* port) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) {
+ return NO_INIT;
+ }
+ const status_t status = statusTFromBinderStatus(mModule->getAudioPort(portId, port));
+ if (status == OK) {
+ auto portIt = mPorts.find(portId);
+ if (portIt != mPorts.end()) {
+ portIt->second = *port;
+ } else {
+ ALOGW("%s, port(%d) returned successfully from the HAL but not it is not cached",
+ __func__, portId);
+ }
+ }
+ return status;
+}
+
void DeviceHalAidl::clearCallbacks(void* cookie) {
std::lock_guard l(mLock);
mCallbacks.erase(cookie);