mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
audio HAL V7: Update track metadata
Add channel mask and audio attributes tags to playback and record track metadata sent to audio HAL. The legacy HAL wrapper supports older legacy HAL versions by sending partial metadata when the legay HAL version is less than 3.2. Bug: 168751366 Test: make Change-Id: Iba3ee3b669e4300201374d4a0d5cf45a04872274
This commit is contained in:
@@ -274,10 +274,21 @@ struct AudioConfig {
|
||||
uint64_t frameCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* AudioTag is an additional use case qualifier complementing
|
||||
* AudioUsage and AudioContentType. Tags are set by vendor specific applications
|
||||
* and must be prefixed by "VX_". Vendor must namespace their tag
|
||||
* names to avoid conflicts.
|
||||
*/
|
||||
typedef string AudioTag;
|
||||
|
||||
/** Metadata of a playback track for a StreamOut. */
|
||||
struct PlaybackTrackMetadata {
|
||||
AudioUsage usage;
|
||||
AudioContentType contentType;
|
||||
/** Tags from AudioTrack audio atttributes */
|
||||
vec<AudioTag> tags;
|
||||
AudioChannelMask channelMask;
|
||||
/**
|
||||
* Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
|
||||
* 2 means double amplification...
|
||||
@@ -294,6 +305,9 @@ struct SourceMetadata {
|
||||
/** Metadata of a record track for a StreamIn. */
|
||||
struct RecordTrackMetadata {
|
||||
AudioSource source;
|
||||
/** Tags from AudioTrack audio atttributes */
|
||||
vec<AudioTag> tags;
|
||||
AudioChannelMask channelMask;
|
||||
/**
|
||||
* Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
|
||||
* 2 means double amplification...
|
||||
|
||||
@@ -77,6 +77,8 @@ struct HidlUtils {
|
||||
#endif
|
||||
|
||||
#if MAJOR_VERSION >= 7
|
||||
static constexpr char sAudioTagSeparator = ';';
|
||||
|
||||
static status_t audioChannelMaskFromHal(audio_channel_mask_t halChannelMask, bool isInput,
|
||||
AudioChannelMask* channelMask);
|
||||
static status_t audioChannelMasksFromHal(const std::vector<std::string>& halChannelMasks,
|
||||
@@ -126,6 +128,7 @@ struct HidlUtils {
|
||||
struct audio_port_config_device_ext* device,
|
||||
struct audio_port_config_mix_ext* mix,
|
||||
struct audio_port_config_session_ext* session);
|
||||
|
||||
#endif // MAJOR_VERSION >= 7
|
||||
|
||||
// V4 and below have DeviceAddress defined in the 'core' interface.
|
||||
|
||||
@@ -478,29 +478,85 @@ Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>&
|
||||
}
|
||||
|
||||
#if MAJOR_VERSION >= 4
|
||||
Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
|
||||
if (mStream->update_sink_metadata == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
|
||||
record_track_metadata StreamIn::convertRecordTrackMetadata(
|
||||
const RecordTrackMetadata& trackMetadata) {
|
||||
record_track_metadata halTrackMetadata = {.gain = trackMetadata.gain};
|
||||
(void)HidlUtils::audioSourceToHal(trackMetadata.source, &halTrackMetadata.source);
|
||||
#if MAJOR_VERSION >= 5
|
||||
if (trackMetadata.destination.getDiscriminator() ==
|
||||
RecordTrackMetadata::Destination::hidl_discriminator::device) {
|
||||
(void)deviceAddressToHal(trackMetadata.destination.device(), &halTrackMetadata.dest_device,
|
||||
halTrackMetadata.dest_device_address);
|
||||
}
|
||||
#endif
|
||||
return halTrackMetadata;
|
||||
}
|
||||
|
||||
void StreamIn::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
|
||||
std::vector<record_track_metadata> halTracks;
|
||||
halTracks.reserve(sinkMetadata.tracks.size());
|
||||
for (auto& metadata : sinkMetadata.tracks) {
|
||||
record_track_metadata halTrackMetadata = {.gain = metadata.gain};
|
||||
(void)HidlUtils::audioSourceToHal(metadata.source, &halTrackMetadata.source);
|
||||
#if MAJOR_VERSION >= 5
|
||||
if (metadata.destination.getDiscriminator() ==
|
||||
RecordTrackMetadata::Destination::hidl_discriminator::device) {
|
||||
(void)deviceAddressToHal(metadata.destination.device(), &halTrackMetadata.dest_device,
|
||||
halTrackMetadata.dest_device_address);
|
||||
}
|
||||
#endif
|
||||
halTracks.push_back(halTrackMetadata);
|
||||
halTracks.push_back(convertRecordTrackMetadata(metadata));
|
||||
}
|
||||
const sink_metadata_t halMetadata = {
|
||||
.track_count = halTracks.size(),
|
||||
.tracks = halTracks.data(),
|
||||
};
|
||||
mStream->update_sink_metadata(mStream, &halMetadata);
|
||||
}
|
||||
|
||||
#if MAJOR_VERSION >= 7
|
||||
record_track_metadata_v7 StreamIn::convertRecordTrackMetadataV7(
|
||||
const RecordTrackMetadata& trackMetadata) {
|
||||
record_track_metadata_v7 halTrackMetadata;
|
||||
halTrackMetadata.base = convertRecordTrackMetadata(trackMetadata);
|
||||
(void)HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
|
||||
&halTrackMetadata.channel_mask);
|
||||
std::string halTags;
|
||||
for (const auto& tag : trackMetadata.tags) {
|
||||
if (&tag != &trackMetadata.tags[0]) {
|
||||
halTags += HidlUtils::sAudioTagSeparator;
|
||||
}
|
||||
halTags += tag.c_str();
|
||||
}
|
||||
strncpy(halTrackMetadata.tags, halTags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
|
||||
return halTrackMetadata;
|
||||
}
|
||||
|
||||
void StreamIn::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
|
||||
std::vector<record_track_metadata_v7> halTracks;
|
||||
halTracks.reserve(sinkMetadata.tracks.size());
|
||||
for (auto& metadata : sinkMetadata.tracks) {
|
||||
halTracks.push_back(convertRecordTrackMetadataV7(metadata));
|
||||
}
|
||||
const sink_metadata_v7_t halMetadata = {
|
||||
.track_count = halTracks.size(),
|
||||
.tracks = halTracks.data(),
|
||||
};
|
||||
mStream->update_sink_metadata_v7(mStream, &halMetadata);
|
||||
}
|
||||
#endif // MAJOR_VERSION >= 7
|
||||
|
||||
Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
|
||||
#if MAJOR_VERSION < 7
|
||||
if (mStream->update_sink_metadata == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
doUpdateSinkMetadata(sinkMetadata);
|
||||
#else
|
||||
if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
|
||||
if (mStream->update_sink_metadata == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
doUpdateSinkMetadata(sinkMetadata);
|
||||
} else {
|
||||
if (mStream->update_sink_metadata_v7 == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
doUpdateSinkMetadataV7(sinkMetadata);
|
||||
}
|
||||
#endif // MAJOR_VERSION < 7
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
@@ -585,26 +585,82 @@ Return<void> StreamOut::debug(const hidl_handle& fd, const hidl_vec<hidl_string>
|
||||
}
|
||||
|
||||
#if MAJOR_VERSION >= 4
|
||||
Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
|
||||
if (mStream->update_source_metadata == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
playback_track_metadata StreamOut::convertPlaybackTrackMetadata(
|
||||
const PlaybackTrackMetadata& trackMetadata) {
|
||||
playback_track_metadata_t halTrackMetadata = {.gain = trackMetadata.gain};
|
||||
(void)HidlUtils::audioUsageToHal(trackMetadata.usage, &halTrackMetadata.usage);
|
||||
(void)HidlUtils::audioContentTypeToHal(trackMetadata.contentType,
|
||||
&halTrackMetadata.content_type);
|
||||
return halTrackMetadata;
|
||||
}
|
||||
|
||||
void StreamOut::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
|
||||
std::vector<playback_track_metadata_t> halTracks;
|
||||
halTracks.reserve(sourceMetadata.tracks.size());
|
||||
for (auto& metadata : sourceMetadata.tracks) {
|
||||
playback_track_metadata_t halTrackMetadata = {.gain = metadata.gain};
|
||||
(void)HidlUtils::audioUsageToHal(metadata.usage, &halTrackMetadata.usage);
|
||||
(void)HidlUtils::audioContentTypeToHal(metadata.contentType,
|
||||
&halTrackMetadata.content_type);
|
||||
halTracks.push_back(std::move(halTrackMetadata));
|
||||
halTracks.push_back(convertPlaybackTrackMetadata(metadata));
|
||||
}
|
||||
const source_metadata_t halMetadata = {
|
||||
.track_count = halTracks.size(),
|
||||
.tracks = halTracks.data(),
|
||||
};
|
||||
mStream->update_source_metadata(mStream, &halMetadata);
|
||||
}
|
||||
|
||||
#if MAJOR_VERSION >= 7
|
||||
playback_track_metadata_v7 StreamOut::convertPlaybackTrackMetadataV7(
|
||||
const PlaybackTrackMetadata& trackMetadata) {
|
||||
playback_track_metadata_v7 halTrackMetadata;
|
||||
halTrackMetadata.base = convertPlaybackTrackMetadata(trackMetadata);
|
||||
(void)HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
|
||||
&halTrackMetadata.channel_mask);
|
||||
std::string halTags;
|
||||
for (const auto& tag : trackMetadata.tags) {
|
||||
if (&tag != &trackMetadata.tags[0]) {
|
||||
halTags += HidlUtils::sAudioTagSeparator;
|
||||
}
|
||||
halTags += tag.c_str();
|
||||
}
|
||||
strncpy(halTrackMetadata.tags, halTags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
|
||||
return halTrackMetadata;
|
||||
}
|
||||
|
||||
void StreamOut::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
|
||||
std::vector<playback_track_metadata_v7> halTracks;
|
||||
halTracks.reserve(sourceMetadata.tracks.size());
|
||||
for (auto& metadata : sourceMetadata.tracks) {
|
||||
halTracks.push_back(convertPlaybackTrackMetadataV7(metadata));
|
||||
}
|
||||
const source_metadata_v7_t halMetadata = {
|
||||
.track_count = halTracks.size(),
|
||||
.tracks = halTracks.data(),
|
||||
};
|
||||
mStream->update_source_metadata_v7(mStream, &halMetadata);
|
||||
}
|
||||
#endif // MAJOR_VERSION >= 7
|
||||
|
||||
Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
|
||||
#if MAJOR_VERSION < 7
|
||||
if (mStream->update_source_metadata == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
doUpdateSourceMetadata(sourceMetadata);
|
||||
#else
|
||||
if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
|
||||
if (mStream->update_source_metadata == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
doUpdateSourceMetadata(sourceMetadata);
|
||||
} else {
|
||||
if (mStream->update_source_metadata_v7 == nullptr) {
|
||||
return Void(); // not supported by the HAL
|
||||
}
|
||||
doUpdateSourceMetadataV7(sourceMetadata);
|
||||
}
|
||||
#endif // MAJOR_VERSION < 7
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Result> StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) {
|
||||
return Result::NOT_SUPPORTED; // TODO: propagate to legacy
|
||||
}
|
||||
|
||||
@@ -146,6 +146,8 @@ struct Device : public IDevice, public ParametersUtil {
|
||||
void closeOutputStream(audio_stream_out_t* stream);
|
||||
audio_hw_device_t* device() const { return mDevice; }
|
||||
|
||||
uint32_t version() const { return mDevice->common.version; }
|
||||
|
||||
private:
|
||||
bool mIsClosed;
|
||||
audio_hw_device_t* mDevice;
|
||||
@@ -161,8 +163,6 @@ struct Device : public IDevice, public ParametersUtil {
|
||||
// Methods from ParametersUtil.
|
||||
char* halGetParameters(const char* keys) override;
|
||||
int halSetParameters(const char* keysAndValues) override;
|
||||
|
||||
uint32_t version() const { return mDevice->common.version; }
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -124,7 +124,16 @@ struct StreamIn : public IStreamIn {
|
||||
static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
|
||||
uint64_t* time);
|
||||
|
||||
private:
|
||||
private:
|
||||
#if MAJOR_VERSION >= 4
|
||||
record_track_metadata convertRecordTrackMetadata(const RecordTrackMetadata& trackMetadata);
|
||||
void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
|
||||
#if MAJOR_VERSION >= 7
|
||||
record_track_metadata_v7 convertRecordTrackMetadataV7(const RecordTrackMetadata& trackMetadata);
|
||||
void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const sp<Device> mDevice;
|
||||
audio_stream_in_t* mStream;
|
||||
const sp<Stream> mStreamCommon;
|
||||
|
||||
@@ -143,6 +143,17 @@ struct StreamOut : public IStreamOut {
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if MAJOR_VERSION >= 4
|
||||
playback_track_metadata convertPlaybackTrackMetadata(
|
||||
const PlaybackTrackMetadata& trackMetadata);
|
||||
void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
|
||||
#if MAJOR_VERSION >= 7
|
||||
playback_track_metadata_v7 convertPlaybackTrackMetadataV7(
|
||||
const PlaybackTrackMetadata& trackMetadata);
|
||||
void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const sp<Device> mDevice;
|
||||
audio_stream_out_t* mStream;
|
||||
const sp<Stream> mStreamCommon;
|
||||
|
||||
@@ -72,7 +72,10 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) {
|
||||
config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
|
||||
hidl_vec<hidl_string> flags;
|
||||
const SinkMetadata initMetadata = {
|
||||
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
|
||||
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
|
||||
.gain = 1,
|
||||
.tags = {},
|
||||
.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
|
||||
#endif
|
||||
EventFlag* efGroup;
|
||||
for (auto microphone : microphones) {
|
||||
@@ -243,7 +246,11 @@ TEST_P(InputStreamTest, updateSinkMetadata) {
|
||||
#if MAJOR_VERSION <= 6
|
||||
const SinkMetadata metadata = {{{.source = source, .gain = volume}}};
|
||||
#elif MAJOR_VERSION >= 7
|
||||
const SinkMetadata metadata = {{{.source = toString(source), .gain = volume}}};
|
||||
const SinkMetadata metadata = {
|
||||
{{.source = toString(source),
|
||||
.gain = volume,
|
||||
.tags = {},
|
||||
.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
|
||||
#endif
|
||||
ASSERT_OK(stream->updateSinkMetadata(metadata))
|
||||
<< "source=" << toString(source) << ", volume=" << volume;
|
||||
@@ -281,7 +288,12 @@ TEST_P(OutputStreamTest, updateSourceMetadata) {
|
||||
#if MAJOR_VERSION <= 6
|
||||
const SourceMetadata metadata = {{{usage, content, volume}}};
|
||||
#elif MAJOR_VERSION >= 7
|
||||
const SourceMetadata metadata = {{{toString(usage), toString(content), volume}}};
|
||||
const SourceMetadata metadata = {
|
||||
{{toString(usage),
|
||||
toString(content),
|
||||
{} /* tags */,
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
|
||||
volume}}};
|
||||
#endif
|
||||
ASSERT_OK(stream->updateSourceMetadata(metadata))
|
||||
<< "usage=" << toString(usage) << ", content=" << toString(content)
|
||||
@@ -300,13 +312,25 @@ TEST_P(OutputStreamTest, updateSourceMetadata) {
|
||||
{AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}
|
||||
#elif MAJOR_VERSION >= 7
|
||||
{{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 0.1},
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
|
||||
{},
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
|
||||
0.1},
|
||||
{toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH), 1.0},
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH),
|
||||
{}, // tags
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
|
||||
1.0},
|
||||
{toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION), 0.0},
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION),
|
||||
{}, // tags
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
|
||||
0.0},
|
||||
{toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN), 0.3}}}
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN),
|
||||
{},
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
|
||||
0.3}}}
|
||||
#endif
|
||||
));
|
||||
// clang-format on
|
||||
|
||||
@@ -98,9 +98,11 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
|
||||
auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
|
||||
#elif MAJOR_VERSION >= 7
|
||||
DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
|
||||
SourceMetadata initMetadata = {
|
||||
{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 1 /* gain */}}};
|
||||
SourceMetadata initMetadata = {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
|
||||
{} /* tags */,
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
|
||||
1 /* gain */}}};
|
||||
hidl_vec<AudioInOutFlag> flags;
|
||||
#endif
|
||||
AudioConfig config{};
|
||||
@@ -131,7 +133,10 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
|
||||
#elif MAJOR_VERSION >= 7
|
||||
DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
|
||||
SinkMetadata initMetadata = {
|
||||
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
|
||||
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
|
||||
.gain = 1,
|
||||
.tags = {},
|
||||
.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
|
||||
hidl_vec<AudioInOutFlag> flags;
|
||||
#endif
|
||||
AudioConfig config{};
|
||||
|
||||
@@ -926,6 +926,8 @@ class OutputStreamTest : public OpenStreamTest<IStreamOut> {
|
||||
const SourceMetadata initMetadata = {
|
||||
{ { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
|
||||
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
|
||||
{},
|
||||
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
|
||||
1 /* gain */ } }};
|
||||
#endif
|
||||
};
|
||||
@@ -991,7 +993,10 @@ class InputStreamTest : public OpenStreamTest<IStreamIn> {
|
||||
const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
|
||||
#elif MAJOR_VERSION >= 7
|
||||
const SinkMetadata initMetadata = {
|
||||
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1}}};
|
||||
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT),
|
||||
.gain = 1,
|
||||
.tags = {},
|
||||
.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user