Audio HAL: add channel mask and tags to track metadata
Add channel mask and audio attributes tags to playback
and record track metadata sent to audio HAL.
Bug: 168751366
Test: make
Change-Id: I06a63963e1be53bd965792dec607fa67a89f28bf
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 195204b..46b510b 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -117,6 +117,8 @@
void closeOutputStream(struct audio_stream_out *stream_out);
void closeInputStream(struct audio_stream_in *stream_in);
+ uint32_t version() const { return mDev->common.version; }
+
private:
audio_hw_device_t *mDev;
@@ -127,8 +129,6 @@
// The destructor automatically closes the device.
virtual ~DeviceHalLocal();
-
- uint32_t version() const { return mDev->common.version; }
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2726e36..09a7c1c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -25,6 +25,7 @@
#include "DeviceHalHidl.h"
#include "EffectHalHidl.h"
+#include "HidlUtils.h"
#include "StreamHalHidl.h"
#include "VersionUtils.h"
@@ -610,12 +611,25 @@
const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
CPP_VERSION::SourceMetadata halMetadata = {
.tracks = transformToHidlVec(sourceMetadata.tracks,
- [](const playback_track_metadata& metadata) -> PlaybackTrackMetadata {
- return {
- .usage=static_cast<AudioUsage>(metadata.usage),
- .contentType=static_cast<AudioContentType>(metadata.content_type),
- .gain=metadata.gain,
+ [](const playback_track_metadata_v7& metadata) -> PlaybackTrackMetadata {
+ PlaybackTrackMetadata halTrackMetadata = {
+ .usage=static_cast<AudioUsage>(metadata.base.usage),
+ .contentType=static_cast<AudioContentType>(metadata.base.content_type),
+ .gain=metadata.base.gain,
};
+#if MAJOR_VERSION >= 7
+ HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, false /*isInput*/,
+ &halTrackMetadata.channelMask);
+
+ std::istringstream tags{metadata.tags};
+ std::string tag;
+ while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+ if (!tag.empty()) {
+ halTrackMetadata.tags.push_back(tag);
+ }
+ }
+#endif
+ return halTrackMetadata;
})};
return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(halMetadata));
}
@@ -902,11 +916,23 @@
StreamInHalInterface::SinkMetadata& sinkMetadata) {
CPP_VERSION::SinkMetadata halMetadata = {
.tracks = transformToHidlVec(sinkMetadata.tracks,
- [](const record_track_metadata& metadata) -> RecordTrackMetadata {
- return {
- .source=static_cast<AudioSource>(metadata.source),
- .gain=metadata.gain,
+ [](const record_track_metadata_v7& metadata) -> RecordTrackMetadata {
+ RecordTrackMetadata halTrackMetadata = {
+ .source=static_cast<AudioSource>(metadata.base.source),
+ .gain=metadata.base.gain,
};
+#if MAJOR_VERSION >= 7
+ HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, true /*isInput*/,
+ &halTrackMetadata.channelMask);
+ std::istringstream tags{metadata.tags};
+ std::string tag;
+ while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+ if (!tag.empty()) {
+ halTrackMetadata.tags.push_back(tag);
+ }
+ }
+#endif
+ return halTrackMetadata;
})};
return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(halMetadata));
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 69be303..f544e06 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -241,19 +241,55 @@
return mStream->get_presentation_position(mStream, frames, timestamp);
}
-status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
- if (mStream->update_source_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamOutHalLocal::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
+ std::vector<playback_track_metadata> halTracks;
+ halTracks.reserve(sourceMetadata.tracks.size());
+ for (auto& metadata : sourceMetadata.tracks) {
+ playback_track_metadata halTrackMetadata;
+ playback_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
+ const source_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_source_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamOutHalLocal::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
const source_metadata_t metadata {
.track_count = sourceMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<playback_track_metadata*>(sourceMetadata.tracks.data()),
+ .tracks = const_cast<playback_track_metadata_v7*>(sourceMetadata.tracks.data()),
};
- mStream->update_source_metadata(mStream, &metadata);
+ mStream->update_source_metadata_v7(mStream, &metadata);
+}
+#endif
+
+status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+#if MAJOR_VERSION < 7
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+ } else {
+ if (mStream->update_source_metadata_v7 == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadataV7(sourceMetadata);
+ }
+#endif
return OK;
}
+
status_t StreamOutHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);
@@ -352,16 +388,52 @@
return mStream->get_capture_position(mStream, frames, time);
}
-status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
- if (mStream->update_sink_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamInHalLocal::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
+ std::vector<record_track_metadata> halTracks;
+ halTracks.reserve(sinkMetadata.tracks.size());
+ for (auto& metadata : sinkMetadata.tracks) {
+ record_track_metadata halTrackMetadata;
+ record_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
- const sink_metadata_t metadata {
+ const sink_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_sink_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamInHalLocal::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
+ const sink_metadata_v7_t halMetadata {
.track_count = sinkMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<record_track_metadata*>(sinkMetadata.tracks.data()),
+ .tracks = const_cast<record_track_metadata_v7*>(sinkMetadata.tracks.data()),
};
- mStream->update_sink_metadata(mStream, &metadata);
+ mStream->update_sink_metadata_v7(mStream, &halMetadata);
+}
+#endif
+
+status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+#if MAJOR_VERSION < 7
+
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+ } else {
+ if (mStream->update_sink_metadata_v7 == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadataV7(sinkMetadata);
+ }
+#endif
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index d17f9f3..8e5180f 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -173,6 +173,9 @@
static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
+
+ void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+ void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
};
class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
@@ -227,6 +230,9 @@
StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
virtual ~StreamInHalLocal();
+
+ void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
+ void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index e30cb72..523705e 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -158,7 +158,7 @@
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
struct SourceMetadata {
- std::vector<playback_track_metadata_t> tracks;
+ std::vector<playback_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's source has been changed.
@@ -197,7 +197,7 @@
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
struct SinkMetadata {
- std::vector<record_track_metadata_t> tracks;
+ std::vector<record_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's sink has been changed.
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a4b8650..dbc190c 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,7 +148,7 @@
*/
bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
- using SourceMetadatas = std::vector<playback_track_metadata_t>;
+ using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
/** Copy the track metadata in the provided iterator. Thread safe. */
virtual void copyMetadataTo(MetadataInserter& backInserter) const;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ab2bc32..cdb4d01 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8097,10 +8097,15 @@
StreamInHalInterface::SinkMetadata metadata;
for (const sp<RecordTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
@@ -9675,11 +9680,15 @@
StreamOutHalInterface::SourceMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ playback_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.usage = track->attributes().usage,
.content_type = track->attributes().content_type,
.gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mOutput->stream->updateSourceMetadata(metadata);
}
@@ -9800,10 +9809,14 @@
StreamInHalInterface::SinkMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
- metadata.tracks.push_back({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 01d5345..38dab5b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -253,6 +253,8 @@
// Called to tally underrun frames in playback.
virtual void tallyUnderrunFrames(size_t /* frames */) {}
+ audio_channel_mask_t channelMask() const { return mChannelMask; }
+
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -278,8 +280,6 @@
size_t frameSize() const { return mFrameSize; }
- audio_channel_mask_t channelMask() const { return mChannelMask; }
-
virtual uint32_t sampleRate() const { return mSampleRate; }
bool isStopped() const {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6049f62..06cbe87 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1310,11 +1310,15 @@
void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
{
- *backInserter++ = {
+ playback_track_metadata_v7_t metadata;
+ metadata.base = {
.usage = mAttr.usage,
.content_type = mAttr.content_type,
.gain = mFinalVolume,
};
+ metadata.channel_mask = mChannelMask,
+ strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ *backInserter++ = metadata;
}
void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {