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/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index cc32aec..2d17596 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -6519,7 +6519,7 @@
mpClientInterface->setParameters(input, String8(param));
free(param);
}
- updateAudioProfiles(device, input, profile->getAudioProfiles());
+ updateAudioProfiles(device, input, profile);
if (!profile->hasValidAudioProfile()) {
ALOGW("checkInputsForDevice() direct input missing param");
desc->close();
@@ -8049,77 +8049,54 @@
void AudioPolicyManager::updateAudioProfiles(const sp<DeviceDescriptor>& devDesc,
audio_io_handle_t ioHandle,
- AudioProfileVector &profiles)
-{
- String8 reply;
- audio_devices_t device = devDesc->type();
-
- // Format MUST be checked first to update the list of AudioProfile
- if (profiles.hasDynamicFormat()) {
- reply = mpClientInterface->getParameters(
- ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
- ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.c_str());
- AudioParameter repliedParameters(reply);
- FormatVector formats;
- if (repliedParameters.get(
- String8(AudioParameter::keyStreamSupportedFormats), reply) == NO_ERROR) {
- formats = formatsFromString(reply.c_str());
- } else if (devDesc->hasValidAudioProfile()) {
- ALOGD("%s: using the device profiles", __func__);
- formats = devDesc->getAudioProfiles().getSupportedFormats();
- } else {
- ALOGE("%s: failed to retrieve format, bailing out", __func__);
- return;
- }
- mReportedFormatsMap[devDesc] = formats;
- if (device == AUDIO_DEVICE_OUT_HDMI
- || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
- modifySurroundFormats(devDesc, &formats);
- }
- addProfilesForFormats(profiles, formats);
+ const sp<IOProfile>& profile) {
+ if (!profile->hasDynamicAudioProfile()) {
+ return;
}
- for (audio_format_t format : profiles.getSupportedFormats()) {
- std::optional<ChannelMaskSet> channelMasks;
- SampleRateSet samplingRates;
- AudioParameter requestedParameters;
- requestedParameters.addInt(String8(AudioParameter::keyFormat), format);
+ audio_port_v7 devicePort;
+ devDesc->toAudioPort(&devicePort);
- if (profiles.hasDynamicRateFor(format)) {
- reply = mpClientInterface->getParameters(
- ioHandle,
- requestedParameters.toString() + ";" +
- AudioParameter::keyStreamSupportedSamplingRates);
- ALOGV("%s: supported sampling rates %s", __FUNCTION__, reply.c_str());
- AudioParameter repliedParameters(reply);
- if (repliedParameters.get(
- String8(AudioParameter::keyStreamSupportedSamplingRates), reply) == NO_ERROR) {
- samplingRates = samplingRatesFromString(reply.c_str());
- } else {
- samplingRates = devDesc->getAudioProfiles().getSampleRatesFor(format);
- }
- }
- if (profiles.hasDynamicChannelsFor(format)) {
- reply = mpClientInterface->getParameters(ioHandle,
- requestedParameters.toString() + ";" +
- AudioParameter::keyStreamSupportedChannels);
- ALOGV("%s: supported channel masks %s", __FUNCTION__, reply.c_str());
- AudioParameter repliedParameters(reply);
- if (repliedParameters.get(
- String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
- channelMasks = channelMasksFromString(reply.c_str());
- } else {
- channelMasks = devDesc->getAudioProfiles().getChannelMasksFor(format);
- }
- if (channelMasks.has_value() && (device == AUDIO_DEVICE_OUT_HDMI
- || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD))) {
- modifySurroundChannelMasks(&channelMasks.value());
- }
- }
- addDynamicAudioProfileAndSort(
- profiles, new AudioProfile(
- format, channelMasks.value_or(ChannelMaskSet()), samplingRates));
+ audio_port_v7 mixPort;
+ profile->toAudioPort(&mixPort);
+ mixPort.ext.mix.handle = ioHandle;
+
+ status_t status = mpClientInterface->getAudioMixPort(&devicePort, &mixPort);
+ if (status != NO_ERROR) {
+ ALOGE("%s failed to query the attributes of the mix port", __func__);
+ return;
}
+
+ std::set<audio_format_t> supportedFormats;
+ for (size_t i = 0; i < mixPort.num_audio_profiles; ++i) {
+ supportedFormats.insert(mixPort.audio_profiles[i].format);
+ }
+ FormatVector formats(supportedFormats.begin(), supportedFormats.end());
+ mReportedFormatsMap[devDesc] = formats;
+
+ if (devDesc->type() == AUDIO_DEVICE_OUT_HDMI ||
+ isDeviceOfModule(devDesc,AUDIO_HARDWARE_MODULE_ID_MSD)) {
+ modifySurroundFormats(devDesc, &formats);
+ size_t modifiedNumProfiles = 0;
+ for (size_t i = 0; i < mixPort.num_audio_profiles; ++i) {
+ if (std::find(formats.begin(), formats.end(), mixPort.audio_profiles[i].format) ==
+ formats.end()) {
+ // Skip the format that is not present after modifying surround formats.
+ continue;
+ }
+ memcpy(&mixPort.audio_profiles[modifiedNumProfiles], &mixPort.audio_profiles[i],
+ sizeof(struct audio_profile));
+ ChannelMaskSet channels(mixPort.audio_profiles[modifiedNumProfiles].channel_masks,
+ mixPort.audio_profiles[modifiedNumProfiles].channel_masks +
+ mixPort.audio_profiles[modifiedNumProfiles].num_channel_masks);
+ modifySurroundChannelMasks(&channels);
+ std::copy(channels.begin(), channels.end(),
+ std::begin(mixPort.audio_profiles[modifiedNumProfiles].channel_masks));
+ mixPort.audio_profiles[modifiedNumProfiles++].num_channel_masks = channels.size();
+ }
+ mixPort.num_audio_profiles = modifiedNumProfiles;
+ }
+ profile->importAudioPort(mixPort);
}
status_t AudioPolicyManager::installPatch(const char *caller,
@@ -8246,7 +8223,7 @@
mpClientInterface->setParameters(output, String8(param));
free(param);
}
- updateAudioProfiles(device, output, profile->getAudioProfiles());
+ updateAudioProfiles(device, output, profile);
if (!profile->hasValidAudioProfile()) {
ALOGW("%s() missing param", __func__);
desc->close();
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 88bafef..440fd01 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1040,9 +1040,9 @@
void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
- // If any, resolve any "dynamic" fields of an Audio Profiles collection
+ // If any, resolve any "dynamic" fields of the Audio Profiles collection of and IOProfile
void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
- AudioProfileVector &profiles);
+ const sp<IOProfile> &profiles);
// Notify the policy client to prepare for disconnecting external device.
void prepareToDisconnectExternalDevice(const sp<DeviceDescriptor> &device);