diff options
-rw-r--r-- | audio/7.0/config/api/current.txt | 8 | ||||
-rw-r--r-- | audio/7.0/config/audio_policy_configuration.xsd | 7 | ||||
-rw-r--r-- | audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h | 4 | ||||
-rw-r--r-- | audio/common/7.0/types.hal | 45 | ||||
-rw-r--r-- | audio/common/all-versions/default/7.0/HidlUtils.cpp | 141 | ||||
-rw-r--r-- | audio/common/all-versions/default/HidlUtils.h | 8 | ||||
-rw-r--r-- | audio/common/all-versions/default/tests/hidlutils_tests.cpp | 81 |
7 files changed, 268 insertions, 26 deletions
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt index 653531d1f1..7d2706cbe9 100644 --- a/audio/7.0/config/api/current.txt +++ b/audio/7.0/config/api/current.txt @@ -155,6 +155,12 @@ package android.audio.policy.configuration.V7_0 { enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET; } + public enum AudioEncapsulationType { + method @NonNull public String getRawName(); + enum_constant public static final android.audio.policy.configuration.V7_0.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937; + enum_constant public static final android.audio.policy.configuration.V7_0.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE; + } + public enum AudioFormat { method @NonNull public String getRawName(); enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC; @@ -488,10 +494,12 @@ package android.audio.policy.configuration.V7_0 { public class Profile { ctor public Profile(); method @Nullable public java.util.List<android.audio.policy.configuration.V7_0.AudioChannelMask> getChannelMasks(); + method @Nullable public android.audio.policy.configuration.V7_0.AudioEncapsulationType getEncapsulationType(); method @Nullable public String getFormat(); method @Nullable public String getName(); method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates(); method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.V7_0.AudioChannelMask>); + method public void setEncapsulationType(@Nullable android.audio.policy.configuration.V7_0.AudioEncapsulationType); method public void setFormat(@Nullable String); method public void setName(@Nullable String); method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>); diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd index ee51aa88c5..2030921453 100644 --- a/audio/7.0/config/audio_policy_configuration.xsd +++ b/audio/7.0/config/audio_policy_configuration.xsd @@ -551,11 +551,18 @@ <xs:simpleType name="channelMasks"> <xs:list itemType="audioChannelMask" /> </xs:simpleType> + <xs:simpleType name="audioEncapsulationType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/> + <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="profile"> <xs:attribute name="name" type="xs:token" use="optional"/> <xs:attribute name="format" type="extendableAudioFormat" use="optional"/> <xs:attribute name="samplingRates" type="samplingRates" use="optional"/> <xs:attribute name="channelMasks" type="channelMasks" use="optional"/> + <xs:attribute name="encapsulationType" type="audioEncapsulationType" use="optional"/> </xs:complexType> <xs:simpleType name="audioGainMode"> <xs:restriction base="xs:string"> diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h index 88dd12e94b..7d83556895 100644 --- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h +++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h @@ -287,6 +287,10 @@ static inline bool isLinearPcm(const std::string& format) { return isLinearPcm(stringToAudioFormat(format)); } +static inline bool isUnknownAudioEncapsulationType(const std::string& encapsulationType) { + return stringToAudioEncapsulationType(encapsulationType) == AudioEncapsulationType::UNKNOWN; +} + } // namespace android::audio::policy::configuration::V7_0 #endif // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal index 4f920e47cc..6fca93e85b 100644 --- a/audio/common/7.0/types.hal +++ b/audio/common/7.0/types.hal @@ -145,6 +145,14 @@ struct AudioConfigBaseOptional { }; /** + * Audio encapsulation type indicates the encapsulation type that is required + * for playback/capture. + * See 'audioEncapsulationType' in audio_policy_configuration.xsd for the list + * of allowed values. + */ +typedef string AudioEncapsulationType; + +/** * Configurations supported for a certain audio format. */ struct AudioProfile { @@ -156,6 +164,35 @@ struct AudioProfile { }; /** + * AudioTransport struct describes the capability of an audio port. The + * capability is described via AudioProfile or raw hardware descriptors for + * for formats that are not supported by the platform. + */ +struct AudioTransport { + safe_union AudioCapability { + /** + * A certain audio format that is known by the platform and its + * corresponding configuration. + */ + AudioProfile profile; + /** + * The audio descriptor that is reported from EDID. See HDMI + * specification 1.4b section 7 and CEA-861-G section 7.5.2 for more + * information. When this value is set, it indicates the standard is + * AUDIO_STANDARD_EDID. + */ + vec<uint8_t> edid; + } audioCapability; + + /** + * The encapsulation type that is required when the framework is using this + * format when playing or capturing to/from a stream or device exposing this + * audio transport. + */ + AudioEncapsulationType encapsulationType; +}; + +/** * Major modes for a mobile device. The current mode setting affects audio * routing. */ @@ -488,8 +525,12 @@ struct AudioPort { * E.g. "telephony_tx" or "fm_tuner". */ string name; - /** List of audio profiles supported by the port. */ - vec<AudioProfile> profiles; + /** + * List of audio transports supported by the audio port. This includes + * supported formats and raw hardware descriptors for formats not supported + * by the platform. + */ + vec<AudioTransport> transports; /** List of gain controls attached to the port. */ vec<AudioGain> gains; /** Parameters that depend on the actual port role. */ diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp index 2949fac293..5a5b5d276a 100644 --- a/audio/common/all-versions/default/7.0/HidlUtils.cpp +++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp @@ -715,6 +715,27 @@ status_t HidlUtils::audioPortExtendedInfoToHal(const AudioPortExtendedInfo& ext, return result; } +status_t HidlUtils::encapsulationTypeFromHal(audio_encapsulation_type_t halEncapsulationType, + AudioEncapsulationType* encapsulationType) { + *encapsulationType = audio_encapsulation_type_to_string(halEncapsulationType); + if (!encapsulationType->empty() && !xsd::isUnknownAudioEncapsulationType(*encapsulationType)) { + return NO_ERROR; + } + ALOGE("Unknown audio encapsulation type value 0x%X", halEncapsulationType); + return BAD_VALUE; +} + +status_t HidlUtils::encapsulationTypeToHal(const AudioEncapsulationType& encapsulationType, + audio_encapsulation_type_t* halEncapsulationType) { + if (!xsd::isUnknownAudioEncapsulationType(encapsulationType) && + audio_encapsulation_type_from_string(encapsulationType.c_str(), halEncapsulationType)) { + return NO_ERROR; + } + ALOGE("Unknown audio encapsulation type \"%s\"", encapsulationType.c_str()); + *halEncapsulationType = AUDIO_ENCAPSULATION_TYPE_NONE; + return BAD_VALUE; +} + status_t HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) { struct audio_port_v7 halPortV7 = {}; audio_populate_audio_port_v7(&halPort, &halPortV7); @@ -758,11 +779,7 @@ status_t HidlUtils::audioPortFromHal(const struct audio_port_v7& halPort, AudioP CONVERT_CHECKED(audioPortExtendedInfoFromHal(halPort.role, halPort.type, halDevice, halMix, halSession, &port->ext, &isInput), result); - port->profiles.resize(halPort.num_audio_profiles); - for (size_t i = 0; i < halPort.num_audio_profiles; ++i) { - CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput, &port->profiles[i]), - result); - } + CONVERT_CHECKED(audioTransportsFromHal(halPort, isInput, &port->transports), result); port->gains.resize(halPort.num_gains); for (size_t i = 0; i < halPort.num_gains; ++i) { CONVERT_CHECKED(audioGainFromHal(halPort.gains[i], isInput, &port->gains[i]), result); @@ -780,15 +797,7 @@ status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port_v7* ALOGE("HIDL Audio Port name is too long: %zu", port.name.size()); result = BAD_VALUE; } - halPort->num_audio_profiles = port.profiles.size(); - if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) { - ALOGE("HIDL Audio Port has too many profiles: %u", halPort->num_audio_profiles); - halPort->num_audio_profiles = AUDIO_PORT_MAX_AUDIO_PROFILES; - result = BAD_VALUE; - } - for (size_t i = 0; i < halPort->num_audio_profiles; ++i) { - CONVERT_CHECKED(audioProfileToHal(port.profiles[i], &halPort->audio_profiles[i]), result); - } + CONVERT_CHECKED(audioTransportsToHal(port.transports, halPort), result); halPort->num_gains = port.gains.size(); if (halPort->num_gains > AUDIO_PORT_MAX_GAINS) { ALOGE("HIDL Audio Port has too many gains: %u", halPort->num_gains); @@ -824,6 +833,110 @@ status_t HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port_v7* return result; } +status_t HidlUtils::audioTransportsFromHal(const struct audio_port_v7& halPort, bool isInput, + hidl_vec<AudioTransport>* transports) { + if (halPort.num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES || + halPort.num_extra_audio_descriptors > AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) { + ALOGE("%s, too many audio profiles(%u) or extra audio descriptors(%u)", __func__, + halPort.num_audio_profiles, halPort.num_extra_audio_descriptors); + return BAD_VALUE; + } + status_t result = NO_ERROR; + transports->resize(halPort.num_audio_profiles + halPort.num_extra_audio_descriptors); + size_t idx = 0; + for (size_t i = 0; i < halPort.num_audio_profiles; ++i) { + auto& transport = (*transports)[idx++]; + transport.audioCapability.profile({}); + CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput, + &transport.audioCapability.profile()), + result); + CONVERT_CHECKED(encapsulationTypeFromHal(halPort.audio_profiles[i].encapsulation_type, + &transport.encapsulationType), + result); + } + for (size_t i = 0; i < halPort.num_extra_audio_descriptors; ++i) { + switch (halPort.extra_audio_descriptors[i].standard) { + case AUDIO_STANDARD_EDID: { + const struct audio_extra_audio_descriptor* extraAudioDescriptor = + &halPort.extra_audio_descriptors[i]; + if (extraAudioDescriptor->descriptor_length <= EXTRA_AUDIO_DESCRIPTOR_SIZE) { + auto& transport = (*transports)[idx++]; + transport.audioCapability.edid( + hidl_vec<uint8_t>(extraAudioDescriptor->descriptor, + extraAudioDescriptor->descriptor + + extraAudioDescriptor->descriptor_length)); + CONVERT_CHECKED( + encapsulationTypeFromHal(extraAudioDescriptor->encapsulation_type, + &transport.encapsulationType), + result); + } else { + ALOGE("%s, invalid descriptor length %u", __func__, + extraAudioDescriptor->descriptor_length); + result = BAD_VALUE; + } + } break; + case AUDIO_STANDARD_NONE: + default: + ALOGE("%s, invalid standard %u", __func__, + halPort.extra_audio_descriptors[i].standard); + result = BAD_VALUE; + break; + } + } + return result; +} + +status_t HidlUtils::audioTransportsToHal(const hidl_vec<AudioTransport>& transports, + struct audio_port_v7* halPort) { + status_t result = NO_ERROR; + halPort->num_audio_profiles = 0; + halPort->num_extra_audio_descriptors = 0; + for (const auto& transport : transports) { + switch (transport.audioCapability.getDiscriminator()) { + case AudioTransport::AudioCapability::hidl_discriminator::profile: + if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) { + ALOGE("%s, too many audio profiles", __func__); + result = BAD_VALUE; + break; + } + CONVERT_CHECKED( + audioProfileToHal(transport.audioCapability.profile(), + &halPort->audio_profiles[halPort->num_audio_profiles]), + result); + CONVERT_CHECKED(encapsulationTypeToHal( + transport.encapsulationType, + &halPort->audio_profiles[halPort->num_audio_profiles++] + .encapsulation_type), + result); + break; + case AudioTransport::AudioCapability::hidl_discriminator::edid: + if (halPort->num_extra_audio_descriptors > AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) { + ALOGE("%s, too many extra audio descriptors", __func__); + result = BAD_VALUE; + break; + } + if (transport.audioCapability.edid().size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) { + ALOGE("%s, wrong edid size %zu", __func__, + transport.audioCapability.edid().size()); + result = BAD_VALUE; + break; + } + struct audio_extra_audio_descriptor* extraAudioDescriptor = + &halPort->extra_audio_descriptors[halPort->num_extra_audio_descriptors++]; + extraAudioDescriptor->standard = AUDIO_STANDARD_EDID; + extraAudioDescriptor->descriptor_length = transport.audioCapability.edid().size(); + memcpy(extraAudioDescriptor->descriptor, transport.audioCapability.edid().data(), + transport.audioCapability.edid().size() * sizeof(uint8_t)); + + CONVERT_CHECKED(encapsulationTypeToHal(transport.encapsulationType, + &extraAudioDescriptor->encapsulation_type), + result); + break; + } + } + return result; +} + status_t HidlUtils::audioProfileFromHal(const struct audio_profile& halProfile, bool isInput, AudioProfile* profile) { status_t result = NO_ERROR; diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h index dd4ca4d8ca..98ecc0754e 100644 --- a/audio/common/all-versions/default/HidlUtils.h +++ b/audio/common/all-versions/default/HidlUtils.h @@ -126,6 +126,10 @@ struct HidlUtils { static hidl_vec<AudioTag> filterOutNonVendorTags(const hidl_vec<AudioTag>& tags); static std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags); static std::vector<std::string> splitAudioTags(const char* halTags); + static status_t audioTransportsFromHal(const struct audio_port_v7& halPort, bool isInput, + hidl_vec<AudioTransport>* transports); + static status_t audioTransportsToHal(const hidl_vec<AudioTransport>& transports, + struct audio_port_v7* halTransport); private: static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask, @@ -145,6 +149,10 @@ struct HidlUtils { struct audio_port_config_device_ext* device, struct audio_port_config_mix_ext* mix, struct audio_port_config_session_ext* session); + static status_t encapsulationTypeFromHal(audio_encapsulation_type_t halEncapsulationType, + AudioEncapsulationType* encapsulationType); + static status_t encapsulationTypeToHal(const AudioEncapsulationType& encapsulationType, + audio_encapsulation_type_t* halEncapsulationType); #endif // MAJOR_VERSION >= 7 diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp index e154453e2b..c9e6fac7b2 100644 --- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp +++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp @@ -47,6 +47,10 @@ static constexpr audio_source_t kInvalidHalSource = static_cast<audio_source_t>( // AUDIO_STREAM_DEFAULT is framework-only static constexpr audio_stream_type_t kInvalidHalStreamType = static_cast<audio_stream_type_t>(-2); static constexpr audio_usage_t kInvalidHalUsage = static_cast<audio_usage_t>(0xFFFFFFFFU); +static constexpr audio_encapsulation_type_t kInvalidEncapsulationType = + static_cast<audio_encapsulation_type_t>(0xFFFFFFFFU); +static constexpr audio_standard_t kInvalidAudioStandard = + static_cast<audio_standard_t>(0xFFFFFFFFU); TEST(HidlUtils, ConvertInvalidChannelMask) { AudioChannelMask invalid; @@ -950,6 +954,53 @@ TEST(HidlUtils, ConvertAudioPortConfig) { EXPECT_TRUE(audio_port_configs_are_equal(&halConfig, &halConfigBack)); } +TEST(HidlUtils, ConvertInvalidAudioTransports) { + hidl_vec<AudioTransport> invalid; + struct audio_port_v7 halInvalid = {}; + halInvalid.num_audio_profiles = 1; + halInvalid.audio_profiles[0].format = kInvalidHalFormat; + halInvalid.audio_profiles[0].encapsulation_type = kInvalidEncapsulationType; + halInvalid.num_extra_audio_descriptors = 1; + halInvalid.extra_audio_descriptors[0].standard = kInvalidAudioStandard; + halInvalid.extra_audio_descriptors[0].descriptor_length = EXTRA_AUDIO_DESCRIPTOR_SIZE + 1; + EXPECT_EQ(BAD_VALUE, + HidlUtils::audioTransportsFromHal(halInvalid, false /*isInput*/, &invalid)); + invalid.resize(2); + AudioProfile invalidProfile; + invalidProfile.format = "random string"; + invalid[0].audioCapability.profile(invalidProfile); + invalid[0].encapsulationType = "random string"; + invalid[0].audioCapability.edid(hidl_vec<uint8_t>(EXTRA_AUDIO_DESCRIPTOR_SIZE + 1)); + invalid[1].encapsulationType = "random string"; + EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsToHal(invalid, &halInvalid)); +} + +TEST(HidlUtils, ConvertAudioTransports) { + hidl_vec<AudioTransport> transports; + transports.resize(2); + AudioProfile profile; + profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); + profile.sampleRates.resize(2); + profile.sampleRates[0] = 44100; + profile.sampleRates[1] = 48000; + profile.channelMasks.resize(2); + profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO); + profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); + transports[0].audioCapability.profile(profile); + hidl_vec<uint8_t> shortAudioDescriptor({0x11, 0x06, 0x01}); + transports[0].encapsulationType = + toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE); + transports[1].audioCapability.edid(std::move(shortAudioDescriptor)); + transports[1].encapsulationType = + toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937); + struct audio_port_v7 halPort; + EXPECT_EQ(NO_ERROR, HidlUtils::audioTransportsToHal(transports, &halPort)); + hidl_vec<AudioTransport> transportsBack; + EXPECT_EQ(NO_ERROR, + HidlUtils::audioTransportsFromHal(halPort, false /*isInput*/, &transportsBack)); + EXPECT_EQ(transports, transportsBack); +} + TEST(HidlUtils, ConvertInvalidAudioPort) { AudioPort invalid; struct audio_port_v7 halInvalid = {}; @@ -958,8 +1009,10 @@ TEST(HidlUtils, ConvertInvalidAudioPort) { halInvalid.num_audio_profiles = 1; halInvalid.audio_profiles[0].format = kInvalidHalFormat; EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortFromHal(halInvalid, &invalid)); - invalid.profiles.resize(1); - invalid.profiles[0].format = "random string"; + invalid.transports.resize(1); + AudioProfile invalidProfile; + invalidProfile.format = "random string"; + invalid.transports[0].audioCapability.profile(invalidProfile); EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortToHal(invalid, &halInvalid)); } @@ -967,14 +1020,22 @@ TEST(HidlUtils, ConvertAudioPort) { AudioPort port = {}; port.id = 42; port.name = "test"; - port.profiles.resize(1); - port.profiles[0].format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); - port.profiles[0].sampleRates.resize(2); - port.profiles[0].sampleRates[0] = 44100; - port.profiles[0].sampleRates[1] = 48000; - port.profiles[0].channelMasks.resize(2); - port.profiles[0].channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO); - port.profiles[0].channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); + port.transports.resize(2); + AudioProfile profile; + profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); + profile.sampleRates.resize(2); + profile.sampleRates[0] = 44100; + profile.sampleRates[1] = 48000; + profile.channelMasks.resize(2); + profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO); + profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); + port.transports[0].audioCapability.profile(profile); + port.transports[0].encapsulationType = + toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE); + hidl_vec<uint8_t> shortAudioDescriptor({0x11, 0x06, 0x01}); + port.transports[1].audioCapability.edid(std::move(shortAudioDescriptor)); + port.transports[1].encapsulationType = + toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937); port.gains.resize(1); port.gains[0].channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); port.ext.device({}); |