Merge "Add AudioTransport to replace AudioProfile in AudioPort." am: 5bbfdbfbeb
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1650659
Change-Id: Id411d36a2e78c89e38e6fd361b1ca987de1f0172
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index 48093c5..eb8c2dd 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -155,6 +155,12 @@
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;
@@ -487,10 +493,12 @@
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 ccaaf98..007e250 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -550,11 +550,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 88dd12e..7d83556 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 @@
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 4f920e4..6fca93e 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -145,6 +145,14 @@
};
/**
+ * 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 @@
};
/**
+ * 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 @@
* 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 2949fac..5a5b5d2 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 @@
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 @@
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 @@
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 @@
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 dd4ca4d..98ecc07 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -126,6 +126,10 @@
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 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 e154453..c9e6fac 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 @@
// 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 @@
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 @@
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 @@
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({});