Merge "Add AudioTransport to replace AudioProfile in AudioPort." am: 5bbfdbfbeb am: 3225bc292a

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1650659

Change-Id: Ie4971d1ac248206517099387e8dfcd89cf26a2a8
This commit is contained in:
Jiabin Huang 2021-03-24 19:51:51 +00:00 committed by Automerger Merge Worker
commit 40d8d1eac6
7 changed files with 268 additions and 26 deletions

View file

@ -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;
@ -487,10 +493,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>);

View file

@ -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">

View file

@ -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

View file

@ -144,6 +144,14 @@ struct AudioConfigBaseOptional {
} channelMask;
};
/**
* 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.
*/
@ -155,6 +163,35 @@ struct AudioProfile {
vec<AudioChannelMask> channelMasks;
};
/**
* 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. */

View file

@ -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;

View file

@ -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

View file

@ -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({});