libaudiohal: Implement updateSource/SinkMetadata
Provide conversions between legacy and AIDL playback and
record track metadata. Use them for implementing
StreamInHalAidl::updateSinkMetadata and
StreamOutHalAidl::updateSourceMetadata.
Bug: 205884982
Bug: 272188499
Test: atest audiorecord_tests trackplayerbase_tests (w/AIDL)
Change-Id: I9278bb7ddbfa926fb1840ba1c51cb2401e949df6
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
index 7c63339..413ae67 100644
--- a/media/audioaidlconversion/AidlConversionNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -14,14 +14,18 @@
* limitations under the License.
*/
+#include <sstream>
#include <utility>
+#include <system/audio.h>
#define LOG_TAG "AidlConversionNdk"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <utils/Errors.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
+#include <Utils.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
// AIDL NDK backend to legacy audio data structure conversion utilities.
@@ -29,6 +33,51 @@
namespace aidl {
namespace android {
+using hardware::audio::common::PlaybackTrackMetadata;
+using hardware::audio::common::RecordTrackMetadata;
+using ::android::BAD_VALUE;
+using ::android::OK;
+
+namespace {
+
+::android::status_t combineString(
+ const std::vector<std::string>& v, char separator, std::string* result) {
+ std::ostringstream oss;
+ for (const auto& s : v) {
+ if (oss.tellp() > 0) {
+ oss << separator;
+ }
+ if (s.find(separator) == std::string::npos) {
+ oss << s;
+ } else {
+ ALOGE("%s: string \"%s\" contains separator character \"%c\"",
+ __func__, s.c_str(), separator);
+ return BAD_VALUE;
+ }
+ }
+ *result = oss.str();
+ return OK;
+}
+
+std::vector<std::string> splitString(const std::string& s, char separator) {
+ std::istringstream iss(s);
+ std::string t;
+ std::vector<std::string> result;
+ while (std::getline(iss, t, separator)) {
+ result.push_back(std::move(t));
+ }
+ return result;
+}
+
+std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags) {
+ std::vector<std::string> result;
+ std::copy_if(tags.begin(), tags.end(), std::back_inserter(result),
+ ::android::hardware::audio::common::maybeVendorExtension);
+ return result;
+}
+
+} // namespace
+
// buffer_provider_t is not supported thus skipped
ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
const media::audio::common::AudioConfigBase& aidl, bool isInput) {
@@ -68,5 +117,79 @@
return aidl;
}
+::android::status_t aidl2legacy_AudioAttributesTags(
+ const std::vector<std::string>& aidl, char* legacy) {
+ std::string aidlTags;
+ RETURN_STATUS_IF_ERROR(combineString(
+ filterOutNonVendorTags(aidl), AUDIO_ATTRIBUTES_TAGS_SEPARATOR, &aidlTags));
+ RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidlTags, legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
+ return OK;
+}
+
+ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy) {
+ std::string legacyTags = VALUE_OR_RETURN(legacy2aidl_string(
+ legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
+ return filterOutNonVendorTags(splitString(legacyTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR));
+}
+
+ConversionResult<playback_track_metadata_v7>
+aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(const PlaybackTrackMetadata& aidl) {
+ playback_track_metadata_v7 legacy;
+ legacy.base.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+ legacy.base.content_type = VALUE_OR_RETURN(aidl2legacy_AudioContentType_audio_content_type_t(
+ aidl.contentType));
+ legacy.base.gain = aidl.gain;
+ legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask, false /*isInput*/));
+ RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
+ return legacy;
+}
+
+ConversionResult<PlaybackTrackMetadata>
+legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
+ const playback_track_metadata_v7& legacy) {
+ PlaybackTrackMetadata aidl;
+ aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.base.usage));
+ aidl.contentType = VALUE_OR_RETURN(legacy2aidl_audio_content_type_t_AudioContentType(
+ legacy.base.content_type));
+ aidl.gain = legacy.base.gain;
+ aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ legacy.channel_mask, false /*isInput*/));
+ aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
+ return aidl;
+}
+
+ConversionResult<record_track_metadata_v7>
+aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(const RecordTrackMetadata& aidl) {
+ record_track_metadata_v7 legacy;
+ legacy.base.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
+ legacy.base.gain = aidl.gain;
+ if (aidl.destinationDevice.has_value()) {
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl.destinationDevice.value(),
+ &legacy.base.dest_device, legacy.base.dest_device_address));
+ } else {
+ legacy.base.dest_device = AUDIO_DEVICE_NONE;
+ }
+ legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask, true /*isInput*/));
+ RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
+ return legacy;
+}
+
+ConversionResult<RecordTrackMetadata>
+legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy) {
+ RecordTrackMetadata aidl;
+ aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.base.source));
+ aidl.gain = legacy.base.gain;
+ if (legacy.base.dest_device != AUDIO_DEVICE_NONE) {
+ aidl.destinationDevice = VALUE_OR_RETURN(legacy2aidl_audio_device_AudioDevice(
+ legacy.base.dest_device, legacy.base.dest_device_address));
+ }
+ aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ legacy.channel_mask, true /*isInput*/));
+ aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
+ return aidl;
+}
+
} // namespace android
} // aidl
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index c0024ef..bdb3a2c 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -135,12 +135,16 @@
],
defaults: [
"audio_aidl_conversion_common_default",
+ "latest_android_hardware_audio_common_ndk_shared",
"latest_android_media_audio_common_types_ndk_shared",
],
shared_libs: [
"libbinder_ndk",
"libbase",
],
+ static_libs: [
+ "libaudioaidlcommon",
+ ],
cflags: [
"-DBACKEND_NDK",
],
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
index 98a7d41..e92f1a9 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -16,17 +16,20 @@
#pragma once
-#include <android/binder_auto_utils.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
/**
- * Can only handle conversion between AIDL (NDK backend) and legacy type.
+ * Can only handle conversion between AIDL (NDK backend) and legacy types.
*/
+
+#include <string>
+#include <vector>
+
#include <hardware/audio_effect.h>
-#include <media/AidlConversionUtil.h>
#include <system/audio_effect.h>
+
+#include <aidl/android/hardware/audio/common/PlaybackTrackMetadata.h>
+#include <aidl/android/hardware/audio/common/RecordTrackMetadata.h>
#include <aidl/android/media/audio/common/AudioConfig.h>
+#include <media/AidlConversionUtil.h>
namespace aidl {
namespace android {
@@ -36,5 +39,22 @@
ConversionResult<media::audio::common::AudioConfigBase> legacy2aidl_buffer_config_t_AudioConfigBase(
const buffer_config_t& legacy, bool isInput);
+::android::status_t aidl2legacy_AudioAttributesTags(
+ const std::vector<std::string>& aidl, char* legacy);
+ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy);
+
+ConversionResult<playback_track_metadata_v7>
+aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(
+ const hardware::audio::common::PlaybackTrackMetadata& aidl);
+ConversionResult<hardware::audio::common::PlaybackTrackMetadata>
+legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
+ const playback_track_metadata_v7& legacy);
+
+ConversionResult<record_track_metadata_v7>
+aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(
+ const hardware::audio::common::RecordTrackMetadata& aidl);
+ConversionResult<hardware::audio::common::RecordTrackMetadata>
+legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy);
+
} // namespace android
} // namespace aidl
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 04b7008..98c655e 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -22,6 +22,7 @@
#include <audio_utils/clock.h>
#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioParameter.h>
#include <mediautils/TimeCheck.h>
@@ -32,6 +33,8 @@
#include "StreamHalAidl.h"
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using ::aidl::android::hardware::audio::common::RecordTrackMetadata;
using ::aidl::android::hardware::audio::core::IStreamCommon;
using ::aidl::android::hardware::audio::core::IStreamIn;
using ::aidl::android::hardware::audio::core::IStreamOut;
@@ -482,6 +485,17 @@
return OK;
}
+// static
+::aidl::ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
+StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy) {
+ ::aidl::android::hardware::audio::common::SourceMetadata aidl;
+ aidl.tracks = VALUE_OR_RETURN(
+ ::aidl::android::convertContainer<std::vector<PlaybackTrackMetadata>>(
+ legacy.tracks,
+ ::aidl::android::legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
+ return aidl;
+}
+
StreamOutHalAidl::StreamOutHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
@@ -507,8 +521,8 @@
AudioParameter parameters(kvPairs);
ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
- if (filterAndUpdateOffloadMetadata(parameters) != OK) {
- ALOGW("%s filtering or updating offload metadata gets failed", __func__);
+ if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
+ ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
}
return StreamHalAidl::setParameters(parameters.toString());
@@ -626,11 +640,12 @@
}
status_t StreamOutHalAidl::updateSourceMetadata(
- const StreamOutHalInterface::SourceMetadata& sourceMetadata __unused) {
+ const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
+ VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
+ return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
}
status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
@@ -788,6 +803,17 @@
return OK;
}
+// static
+::aidl::ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
+StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
+ ::aidl::android::hardware::audio::common::SinkMetadata aidl;
+ aidl.tracks = VALUE_OR_RETURN(
+ ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
+ legacy.tracks,
+ ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
+ return aidl;
+}
+
StreamInHalAidl::StreamInHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
const std::shared_ptr<IStreamIn>& stream)
@@ -837,11 +863,12 @@
}
status_t StreamInHalAidl::updateSinkMetadata(
- const StreamInHalInterface::SinkMetadata& sinkMetadata __unused) {
+ const StreamInHalInterface::SinkMetadata& sinkMetadata) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
+ VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
+ return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
}
status_t StreamInHalAidl::setPreferredMicrophoneDirection(
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 8e59513..e3cae77 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -313,6 +313,9 @@
private:
friend class sp<StreamOutHalAidl>;
+ static ::aidl::ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
+ legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy);
+
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
const wp<CallbackBroker> mCallbackBroker;
@@ -362,6 +365,9 @@
private:
friend class sp<StreamInHalAidl>;
+ static ::aidl::ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
+ legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy);
+
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn> mStream;
// Can not be constructed directly by clients.