From deebf381f6d0a09975df4e239be30ecc3d4c5bfa Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 20 Nov 2020 18:42:21 +0100 Subject: [PATCH] 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 --- audio/common/7.0/types.hal | 14 ++++ audio/common/all-versions/default/HidlUtils.h | 3 + audio/core/all-versions/default/StreamIn.cpp | 82 ++++++++++++++++--- audio/core/all-versions/default/StreamOut.cpp | 74 +++++++++++++++-- .../default/include/core/default/Device.h | 4 +- .../default/include/core/default/StreamIn.h | 11 ++- .../default/include/core/default/StreamOut.h | 11 +++ .../4.0/AudioPrimaryHidlHalTest.cpp | 38 +++++++-- .../6.0/AudioPrimaryHidlHalTest.cpp | 13 ++- .../vts/functional/AudioPrimaryHidlHalTest.h | 7 +- 10 files changed, 220 insertions(+), 37 deletions(-) diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal index ed56c7320f..b14ebd48d9 100644 --- a/audio/common/7.0/types.hal +++ b/audio/common/7.0/types.hal @@ -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 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 tags; + AudioChannelMask channelMask; /** * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation, * 2 means double amplification... diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h index a0bd1bc27e..d8b7ba419e 100644 --- a/audio/common/all-versions/default/HidlUtils.h +++ b/audio/common/all-versions/default/HidlUtils.h @@ -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& 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. diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp index ead7204712..a6735546f3 100644 --- a/audio/core/all-versions/default/StreamIn.cpp +++ b/audio/core/all-versions/default/StreamIn.cpp @@ -478,29 +478,85 @@ Return StreamIn::debug(const hidl_handle& fd, const hidl_vec& } #if MAJOR_VERSION >= 4 -Return 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 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 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 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(); } diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp index 5633cbb4b7..2451b9eb3a 100644 --- a/audio/core/all-versions/default/StreamOut.cpp +++ b/audio/core/all-versions/default/StreamOut.cpp @@ -585,26 +585,82 @@ Return StreamOut::debug(const hidl_handle& fd, const hidl_vec } #if MAJOR_VERSION >= 4 -Return 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 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 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 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 StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) { return Result::NOT_SUPPORTED; // TODO: propagate to legacy } diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h index 461c253768..2a4d22651a 100644 --- a/audio/core/all-versions/default/include/core/default/Device.h +++ b/audio/core/all-versions/default/include/core/default/Device.h @@ -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 diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h index b861c6cc2b..512da559bf 100644 --- a/audio/core/all-versions/default/include/core/default/StreamIn.h +++ b/audio/core/all-versions/default/include/core/default/StreamIn.h @@ -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 mDevice; audio_stream_in_t* mStream; const sp mStreamCommon; diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h index 9f64e3e77d..8da940d846 100644 --- a/audio/core/all-versions/default/include/core/default/StreamOut.h +++ b/audio/core/all-versions/default/include/core/default/StreamOut.h @@ -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 mDevice; audio_stream_out_t* mStream; const sp mStreamCommon; diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp index 1612d3c30c..a7d7ed104b 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp @@ -72,7 +72,10 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); hidl_vec 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 diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp index bd8de2d0e6..5ad38de412 100644 --- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp @@ -98,9 +98,11 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) { auto flags = hidl_bitfield(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 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 flags; #endif AudioConfig config{}; diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index 05c9bf7e2e..63330233ee 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -926,6 +926,8 @@ class OutputStreamTest : public OpenStreamTest { 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 { 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 };