audio: Create libraries for data types in core and effect
Add 'CoreUtils' library similar to 'HidlUtils' for the types
specific to the core HAL. Add 'EffectUtils' library similar to
'HidlUtils' for the types specific to the effects HAL. Move into
them and de-duplicate code previously scattered across the
default HAL implementation and libaudiohal. Add unit tests.
Removed 'AUDIO_{INPUT|OUTPUT}_FLAG_NONE' from the list of
values in the XSD file to avoid additional complexity due to
equivalence of this value to an empty list of flags.
Bug: 142480271
Test: m android.hardware.audio@X.0-impl
Test: m android.hardware.audio.effect@X.0-impl
Test: atest android.hardware.audio@7.0-util_tests
Test: atest android.hardware.audio.common@7.0-util_tests
Test: atest android.hardware.audio.effect@7.0-util_tests
Change-Id: I71a95cbe07fcc162dc6d74ff9665747a17ce5a80
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index f585d8e..78f2f29 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -251,7 +251,6 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
- enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_NONE;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
@@ -265,7 +264,6 @@
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
- enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NONE;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 87e5774..50c1793 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -159,13 +159,9 @@
<xs:annotation>
<xs:documentation xml:lang="en">
The flags indicate suggested stream attributes supported by the profile.
- Use of AUDIO_{INPUT|OUTPUT}_FLAG_NONE in the XML file isn't required
- as empty flag lists are allowed. However these constants are useful for
- representing an empty enum value.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
- <xs:enumeration value="AUDIO_OUTPUT_FLAG_NONE" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_PRIMARY" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_FAST" />
@@ -182,7 +178,6 @@
<xs:enumeration value="AUDIO_OUTPUT_FLAG_VOIP_RX" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
- <xs:enumeration value="AUDIO_INPUT_FLAG_NONE" />
<xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
<xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
diff --git a/audio/README.md b/audio/README.md
index b77b9ba..1938ad4 100644
--- a/audio/README.md
+++ b/audio/README.md
@@ -7,47 +7,49 @@
## Directory Structure
-* `2.0` -- version 2.0 of the core HIDL API. Note that `.hal` files
+* `2.0` — version 2.0 of the core HIDL API. Note that `.hal` files
can not be moved into the `core` directory because that would change
its namespace and include path.
- - `config` -- the XSD schema for the Audio Policy Manager
+ - `config` — the XSD schema for the Audio Policy Manager
configuration file.
-* `4.0` -- version 4.0 of the core HIDL API.
+* `4.0` — version 4.0 of the core HIDL API.
* ...
-* `common` -- common types for audio core and effect HIDL API.
- - `2.0` -- version 2.0 of the common types HIDL API.
- - `4.0` -- version 4.0.
+* `common` — common types for audio core and effect HIDL API.
+ - `2.0` — version 2.0 of the common types HIDL API.
+ - `4.0` — version 4.0.
- ...
- - `7.0` -- version 7.0.
- - `example` -- example implementation of the core and effect
+ - `7.0` — version 7.0.
+ - `example` — example implementation of the core and effect
V7.0 API. It represents a "fake" audio HAL that doesn't
actually communicate with hardware.
- - `all-versions` -- code common to all version of both core and effect API.
- - `default` -- shared code of the default implementation.
- - `service` -- vendor HAL service for hosting the default
+ - `all-versions` — code common to all version of both core and effect API.
+ - `default` — shared code of the default implementation.
+ - `service` — vendor HAL service for hosting the default
implementation.
- - `test` -- utilities used by tests.
- - `util` -- utilities used by both implementation and tests.
-* `core` -- VTS tests and the default implementation of the core API
+ - `test` — utilities used by tests.
+ - `util` — utilities used by both implementation and tests.
+* `core` — VTS tests and the default implementation of the core API
(not HIDL API, it's in `audio/N.M`).
- - `7.0` -- code specific to version V7.0 of the core HIDL API
- - `all-versions` -- the code is common between all versions,
+ - `7.0` — code specific to version V7.0 of the core HIDL API
+ - `all-versions` — the code is common between all versions,
version-specific parts are enclosed into conditional directives
of preprocessor or reside in dedicated files.
- - `default` -- code that wraps the legacy API (from
+ - `default` — code that wraps the legacy API (from
`hardware/libhardware`).
+ - `util` — utilities for the default implementation.
- `vts` VTS tests for the core HIDL API.
-* `effect` -- same for the effect HIDL API.
+* `effect` — same for the effect HIDL API.
- `2.0`
- - `config` -- the XSD schema for the Audio Effects configuration
- file.
+ - `config` — the XSD schema for the Audio Effects configuration file.
- `4.0`
- ...
- `all-versions`
- - `default`
- - `vts`
-* `policy` -- Configurable Audio Policy schemes.
- - `1.0` -- note that versions of CAP are not linked to the versions
+ - `default` — code that wraps the legacy API (from
+ `hardware/libhardware`).
+ - `util` — utilities for the default implementation.
+ - `vts` VTS tests for the effect HIDL API.
+* `policy` — Configurable Audio Policy schemes.
+ - `1.0` — note that versions of CAP are not linked to the versions
of audio HAL.
- - `vts` -- VTS tests for validating actual configuration files.
- - `xml` -- XSD schemas for CAP configuration files.
+ - `vts` — VTS tests for validating actual configuration files.
+ - `xml` — XSD schemas for CAP configuration files.
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index c0042db..b427f3a 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -212,10 +212,16 @@
return isOutputDevice(stringToAudioDevice(device));
}
+static inline bool maybeVendorExtension(const std::string& s) {
+ // Only checks whether the string starts with the "vendor prefix".
+ static const std::string vendorPrefix = "VX_";
+ return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
+}
+
static inline bool isVendorExtension(const std::string& s) {
// Must match the "vendorExtension" rule from the XSD file.
static const std::string vendorPrefix = "VX_";
- return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix &&
+ return maybeVendorExtension(s) &&
std::all_of(s.begin() + vendorPrefix.size(), s.end(),
[](unsigned char c) { return c == '_' || std::isalnum(c); });
}
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index 3903a0b..99c2e5a 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -309,15 +309,15 @@
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...
* Must not be negative.
*/
float gain;
+ AudioChannelMask channelMask;
+ /** Tags from AudioTrack audio atttributes */
+ vec<AudioTag> tags;
};
/** Metadatas of the source of a StreamOut. */
@@ -328,9 +328,6 @@
/** 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...
@@ -344,6 +341,9 @@
Monostate unspecified;
DeviceAddress device;
} destination;
+ AudioChannelMask channelMask;
+ /** Tags from AudioTrack audio atttributes */
+ vec<AudioTag> tags;
};
/** Metadatas of the sink of a StreamIn. */
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index f09db5e..bb3a596 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <string.h>
+#include <algorithm>
#define LOG_TAG "HidlUtils"
#include <log/log.h>
@@ -281,7 +282,7 @@
hidl_vec<AudioGainMode>* gainModeMask) {
status_t status = NO_ERROR;
std::vector<AudioGainMode> result;
- for (uint32_t bit = 0; bit < sizeof(audio_gain_mode_t) * 8; ++bit) {
+ for (uint32_t bit = 0; halGainModeMask != 0 && bit < sizeof(audio_gain_mode_t) * 8; ++bit) {
audio_gain_mode_t flag = static_cast<audio_gain_mode_t>(1u << bit);
if ((flag & halGainModeMask) == flag) {
AudioGainMode flagStr = audio_gain_mode_to_string(flag);
@@ -291,6 +292,7 @@
ALOGE("Unknown audio gain mode value 0x%X", flag);
status = BAD_VALUE;
}
+ halGainModeMask = static_cast<audio_gain_mode_t>(halGainModeMask & ~flag);
}
}
*gainModeMask = result;
@@ -858,15 +860,17 @@
return result;
}
-status_t HidlUtils::audioTagsFromHal(const char* halTags, hidl_vec<AudioTag>* tags) {
- std::vector<std::string> strTags = utils::splitString(halTags, sAudioTagSeparator);
+status_t HidlUtils::audioTagsFromHal(const std::vector<std::string>& strTags,
+ hidl_vec<AudioTag>* tags) {
status_t result = NO_ERROR;
tags->resize(strTags.size());
size_t to = 0;
for (size_t from = 0; from < strTags.size(); ++from) {
- if (xsd::isVendorExtension(strTags[from])) {
- (*tags)[to++] = strTags[from];
+ const auto& tag = strTags[from];
+ if (xsd::isVendorExtension(tag)) {
+ (*tags)[to++] = tag;
} else {
+ ALOGE("Vendor extension tag is ill-formed: \"%s\"", tag.c_str());
result = BAD_VALUE;
}
}
@@ -889,6 +893,7 @@
halTagsBuffer << tag;
hasValue = true;
} else {
+ ALOGE("Vendor extension tag is ill-formed: \"%s\"", tag.c_str());
result = BAD_VALUE;
}
}
@@ -899,6 +904,31 @@
return result;
}
+hidl_vec<AudioTag> HidlUtils::filterOutNonVendorTags(const hidl_vec<AudioTag>& tags) {
+ hidl_vec<AudioTag> result;
+ result.resize(tags.size());
+ size_t resultIdx = 0;
+ for (const auto& tag : tags) {
+ if (xsd::maybeVendorExtension(tag)) {
+ result[resultIdx++] = tag;
+ }
+ }
+ if (resultIdx != result.size()) {
+ result.resize(resultIdx);
+ }
+ return result;
+}
+
+std::vector<std::string> HidlUtils::filterOutNonVendorTags(const std::vector<std::string>& tags) {
+ std::vector<std::string> result;
+ std::copy_if(tags.begin(), tags.end(), std::back_inserter(result), xsd::maybeVendorExtension);
+ return result;
+}
+
+std::vector<std::string> HidlUtils::splitAudioTags(const char* halTags) {
+ return utils::splitString(halTags, sAudioTagSeparator);
+}
+
status_t HidlUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
const char* halDeviceAddress, DeviceAddress* device) {
status_t result = NO_ERROR;
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index cc4fbf2..22b7152 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -20,6 +20,8 @@
#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
#include <memory>
+#include <string>
+#include <vector>
#include <system/audio.h>
@@ -118,8 +120,12 @@
AudioStreamType* streamType);
static status_t audioStreamTypeToHal(const AudioStreamType& streamType,
audio_stream_type_t* halStreamType);
- static status_t audioTagsFromHal(const char* halTags, hidl_vec<AudioTag>* tags);
+ static status_t audioTagsFromHal(const std::vector<std::string>& strTags,
+ hidl_vec<AudioTag>* tags);
static status_t audioTagsToHal(const hidl_vec<AudioTag>& tags, char* halTags);
+ 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);
private:
static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
diff --git a/audio/common/all-versions/default/UuidUtils.cpp b/audio/common/all-versions/default/UuidUtils.cpp
index 85edc7b..6c4c94d 100644
--- a/audio/common/all-versions/default/UuidUtils.cpp
+++ b/audio/common/all-versions/default/UuidUtils.cpp
@@ -42,6 +42,14 @@
memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
}
+std::string UuidUtils::uuidToString(const audio_uuid_t& halUuid) {
+ char str[64];
+ snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", halUuid.timeLow,
+ halUuid.timeMid, halUuid.timeHiAndVersion, halUuid.clockSeq, halUuid.node[0],
+ halUuid.node[1], halUuid.node[2], halUuid.node[3], halUuid.node[4], halUuid.node[5]);
+ return str;
+}
+
} // namespace implementation
} // namespace CPP_VERSION
} // namespace common
diff --git a/audio/common/all-versions/default/UuidUtils.h b/audio/common/all-versions/default/UuidUtils.h
index 38db48a..cd04fb0 100644
--- a/audio/common/all-versions/default/UuidUtils.h
+++ b/audio/common/all-versions/default/UuidUtils.h
@@ -17,14 +17,14 @@
#ifndef android_hardware_audio_Uuid_Utils_H_
#define android_hardware_audio_Uuid_Utils_H_
+#include <string>
+
// clang-format off
#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
// clang-format on
#include <system/audio.h>
-using ::android::hardware::hidl_vec;
-
namespace android {
namespace hardware {
namespace audio {
@@ -38,6 +38,7 @@
public:
static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
+ static std::string uuidToString(const audio_uuid_t& halUuid);
};
} // namespace implementation
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index 642ece3..40fc5c8 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -762,9 +762,7 @@
TEST(HidlUtils, ConvertOffloadInfo) {
AudioOffloadInfo offloadInfo = {};
- offloadInfo.base.sampleRateHz = 44100;
- offloadInfo.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
- offloadInfo.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ offloadInfo.base = generateValidConfigBase(false /*isInput*/);
offloadInfo.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
offloadInfo.bitRatePerSecond = 320;
offloadInfo.durationMicroseconds = -1;
@@ -783,33 +781,76 @@
TEST(HidlUtils, ConvertInvalidConfig) {
AudioConfig invalid;
- audio_config_t halInvalid = AUDIO_CONFIG_INITIALIZER;
- halInvalid.channel_mask = kInvalidHalChannelMask;
- halInvalid.format = kInvalidHalFormat;
- EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigFromHal(halInvalid, false /*isInput*/, &invalid));
- EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigFromHal(halInvalid, true /*isInput*/, &invalid));
- invalid.base.channelMask = "random string";
- invalid.base.format = "random string";
- EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalid, &halInvalid));
+ audio_config_t halInvalidChannelMask = AUDIO_CONFIG_INITIALIZER;
+ halInvalidChannelMask.channel_mask = kInvalidHalChannelMask;
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::audioConfigFromHal(halInvalidChannelMask, false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::audioConfigFromHal(halInvalidChannelMask, true /*isInput*/, &invalid));
+ audio_config_t halInvalidFormat = AUDIO_CONFIG_INITIALIZER;
+ halInvalidFormat.format = kInvalidHalFormat;
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::audioConfigFromHal(halInvalidFormat, false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE,
+ HidlUtils::audioConfigFromHal(halInvalidFormat, true /*isInput*/, &invalid));
+
+ AudioConfig invalidChannelMask;
+ audio_config_t halInvalid;
+ invalidChannelMask.base.channelMask = "random string";
+ invalidChannelMask.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_DEFAULT);
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalidChannelMask, &halInvalid));
+ AudioConfig invalidFormat;
+ invalidFormat.base.format = "random string";
+ invalidFormat.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalidFormat, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertConfigDefault) {
+ audio_config_t halDefault = AUDIO_CONFIG_INITIALIZER;
+ AudioConfig defaultOut, defaultIn;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halDefault, false /*isInput*/, &defaultOut));
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halDefault, true /*isInput*/, &defaultIn));
+ EXPECT_EQ(defaultOut, defaultIn);
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(defaultOut, &halDefault));
+
+ // Note: empty channel mask and config are not valid values.
+ AudioConfig defaultCfg{};
+ defaultCfg.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ defaultCfg.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_DEFAULT);
+ audio_config_t halDefaultCfg;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(defaultCfg, &halDefaultCfg));
+ AudioConfig defaultCfgBackOut, defaultCfgBackIn;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioConfigFromHal(halDefaultCfg, false /*isInput*/, &defaultCfgBackOut));
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioConfigFromHal(halDefaultCfg, true /*isInput*/, &defaultCfgBackIn));
+ EXPECT_EQ(defaultCfgBackOut, defaultCfgBackIn);
+ EXPECT_EQ(defaultCfg, defaultCfgBackOut);
}
TEST(HidlUtils, ConvertConfig) {
- AudioConfig config = {};
- config.base.sampleRateHz = 44100;
- config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
- config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
- audio_config_t halConfig;
- EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(config, &halConfig));
- AudioConfig configBack;
- EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halConfig, false /*isInput*/, &configBack));
- EXPECT_EQ(config, configBack);
+ AudioConfig configOut{};
+ configOut.base = generateValidConfigBase(false /*isInput*/);
+ audio_config_t halConfigOut;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(configOut, &halConfigOut));
+ AudioConfig configOutBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioConfigFromHal(halConfigOut, false /*isInput*/, &configOutBack));
+ EXPECT_EQ(configOut, configOutBack);
+
+ AudioConfig configIn{};
+ configIn.base = generateValidConfigBase(true /*isInput*/);
+ audio_config_t halConfigIn;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(configIn, &halConfigIn));
+ AudioConfig configInBack;
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioConfigFromHal(halConfigIn, true /*isInput*/, &configInBack));
+ EXPECT_EQ(configIn, configInBack);
}
TEST(HidlUtils, ConvertConfigWithOffloadInfo) {
AudioConfig config = {};
- config.base.sampleRateHz = 44100;
- config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
- config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ config.base = generateValidConfigBase(false /*isInput*/);
config.offloadInfo.info(
AudioOffloadInfo{.base = config.base,
.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC),
@@ -952,20 +993,51 @@
char halEmptyTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(emptyTags, halEmptyTags));
hidl_vec<AudioTag> emptyTagsBack;
- EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halEmptyTags, &emptyTagsBack));
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halEmptyTags), &emptyTagsBack));
EXPECT_EQ(emptyTags, emptyTagsBack);
hidl_vec<AudioTag> oneTag = {{"VX_GOOGLE_VR"}};
char halOneTag[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(oneTag, halOneTag));
hidl_vec<AudioTag> oneTagBack;
- EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halOneTag, &oneTagBack));
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halOneTag), &oneTagBack));
EXPECT_EQ(oneTag, oneTagBack);
hidl_vec<AudioTag> twoTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
char halTwoTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(twoTags, halTwoTags));
hidl_vec<AudioTag> twoTagsBack;
- EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halTwoTags, &twoTagsBack));
+ EXPECT_EQ(NO_ERROR,
+ HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halTwoTags), &twoTagsBack));
EXPECT_EQ(twoTags, twoTagsBack);
}
+
+template <typename T>
+class FilterTest : public ::testing::Test {};
+using FilterTestTypeParams = ::testing::Types<hidl_vec<AudioTag>, std::vector<std::string>>;
+TYPED_TEST_SUITE(FilterTest, FilterTestTypeParams);
+
+TYPED_TEST(FilterTest, FilterOutNonVendorTags) {
+ TypeParam emptyTags;
+ EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(emptyTags));
+
+ TypeParam allVendorTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
+ EXPECT_EQ(allVendorTags, HidlUtils::filterOutNonVendorTags(allVendorTags));
+
+ TypeParam oneVendorTag = {{"", "VX_GOOGLE_VR", "random_string"}};
+ TypeParam oneVendorTagOnly = HidlUtils::filterOutNonVendorTags(oneVendorTag);
+ EXPECT_EQ(1, oneVendorTagOnly.size());
+ EXPECT_EQ(oneVendorTag[1], oneVendorTagOnly[0]);
+
+ // The vendor extension isn't valid, however it must not be filtered out
+ // so the converter can detect the issue.
+ TypeParam oneMaybeVendorTag = {{"", "random string", "VX_GOOGLE_$$"}};
+ TypeParam oneMaybeVendorTagOnly = HidlUtils::filterOutNonVendorTags(oneMaybeVendorTag);
+ EXPECT_EQ(1, oneMaybeVendorTagOnly.size());
+ EXPECT_EQ(oneMaybeVendorTag[2], oneMaybeVendorTagOnly[0]);
+
+ TypeParam noVendorTags = {{"", "random string", "V_"}};
+ EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(noVendorTags));
+}
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index c75c779..e0f0894 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -1,7 +1,6 @@
filegroup {
name: "android.hardware.audio-impl_srcs",
srcs: [
- "Conversions.cpp",
"Device.cpp",
"DevicesFactory.cpp",
"ParametersUtil.cpp",
@@ -64,6 +63,7 @@
defaults: ["android.hardware.audio-impl_default"],
shared_libs: [
"android.hardware.audio@2.0",
+ "android.hardware.audio@2.0-util",
"android.hardware.audio.common@2.0",
"android.hardware.audio.common@2.0-util",
],
@@ -80,6 +80,7 @@
shared_libs: [
"android.hardware.audio@4.0",
+ "android.hardware.audio@4.0-util",
"android.hardware.audio.common@4.0",
"android.hardware.audio.common@4.0-util",
],
@@ -95,6 +96,7 @@
defaults: ["android.hardware.audio-impl_default"],
shared_libs: [
"android.hardware.audio@5.0",
+ "android.hardware.audio@5.0-util",
"android.hardware.audio.common@5.0",
"android.hardware.audio.common@5.0-util",
],
@@ -110,6 +112,7 @@
defaults: ["android.hardware.audio-impl_default"],
shared_libs: [
"android.hardware.audio@6.0",
+ "android.hardware.audio@6.0-util",
"android.hardware.audio.common@6.0",
"android.hardware.audio.common@6.0-util",
],
@@ -130,6 +133,7 @@
defaults: ["android.hardware.audio-impl_default"],
shared_libs: [
"android.hardware.audio@7.0",
+ "android.hardware.audio@7.0-util",
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
"android.hardware.audio.common@7.0-util",
diff --git a/audio/core/all-versions/default/Conversions.cpp b/audio/core/all-versions/default/Conversions.cpp
deleted file mode 100644
index f1752cc..0000000
--- a/audio/core/all-versions/default/Conversions.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "core/default/Conversions.h"
-
-#include <stdio.h>
-
-#if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#endif
-#include <HidlUtils.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-
-#define CONVERT_CHECKED(expr, result) \
- if (status_t status = (expr); status != NO_ERROR) { \
- result = status; \
- }
-
-status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
- char* halDeviceAddress) {
-#if MAJOR_VERSION >= 5
- return HidlUtils::deviceAddressToHal(device, halDeviceType, halDeviceAddress);
-#else
- return HidlUtils::deviceAddressToHalImpl(device, halDeviceType, halDeviceAddress);
-#endif
-}
-
-status_t deviceAddressFromHal(audio_devices_t halDeviceType, const char* halDeviceAddress,
- DeviceAddress* device) {
-#if MAJOR_VERSION >= 5
- return HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, device);
-#else
- return HidlUtils::deviceAddressFromHalImpl(halDeviceType, halDeviceAddress, device);
-#endif
-}
-
-#if MAJOR_VERSION >= 4
-bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
- const struct audio_microphone_characteristic_t& src) {
- bool status = false;
- if (pDst != NULL) {
- pDst->deviceId = src.device_id;
-
- if (deviceAddressFromHal(src.device, src.address, &pDst->deviceAddress) != OK) {
- return false;
- }
- pDst->channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX);
- for (size_t ch = 0; ch < pDst->channelMapping.size(); ch++) {
- pDst->channelMapping[ch] = AudioMicrophoneChannelMapping(src.channel_mapping[ch]);
- }
- pDst->location = AudioMicrophoneLocation(src.location);
- pDst->group = (AudioMicrophoneGroup)src.group;
- pDst->indexInTheGroup = (uint32_t)src.index_in_the_group;
- pDst->sensitivity = src.sensitivity;
- pDst->maxSpl = src.max_spl;
- pDst->minSpl = src.min_spl;
- pDst->directionality = AudioMicrophoneDirectionality(src.directionality);
- pDst->frequencyResponse.resize(src.num_frequency_responses);
- for (size_t k = 0; k < src.num_frequency_responses; k++) {
- pDst->frequencyResponse[k].frequency = src.frequency_responses[0][k];
- pDst->frequencyResponse[k].level = src.frequency_responses[1][k];
- }
- pDst->position.x = src.geometric_location.x;
- pDst->position.y = src.geometric_location.y;
- pDst->position.z = src.geometric_location.z;
-
- pDst->orientation.x = src.orientation.x;
- pDst->orientation.y = src.orientation.y;
- pDst->orientation.z = src.orientation.z;
-
- status = true;
- }
- return status;
-}
-
-status_t sinkMetadataToHal(const SinkMetadata& sinkMetadata,
- std::vector<record_track_metadata>* halTracks) {
- status_t result = NO_ERROR;
- if (halTracks != nullptr) {
- halTracks->reserve(sinkMetadata.tracks.size());
- }
- for (auto& metadata : sinkMetadata.tracks) {
- record_track_metadata halTrackMetadata{.gain = metadata.gain};
- CONVERT_CHECKED(HidlUtils::audioSourceToHal(metadata.source, &halTrackMetadata.source),
- result);
-#if MAJOR_VERSION >= 5
- if (metadata.destination.getDiscriminator() ==
- RecordTrackMetadata::Destination::hidl_discriminator::device) {
- CONVERT_CHECKED(
- deviceAddressToHal(metadata.destination.device(), &halTrackMetadata.dest_device,
- halTrackMetadata.dest_device_address),
- result);
- }
-#endif
- if (halTracks != nullptr) {
- halTracks->push_back(std::move(halTrackMetadata));
- }
- }
- return result;
-}
-
-status_t sourceMetadataToHal(const SourceMetadata& sourceMetadata,
- std::vector<playback_track_metadata_t>* halTracks) {
- status_t result = NO_ERROR;
- if (halTracks != nullptr) {
- halTracks->reserve(sourceMetadata.tracks.size());
- }
- for (auto& metadata : sourceMetadata.tracks) {
- playback_track_metadata_t halTrackMetadata{.gain = metadata.gain};
- CONVERT_CHECKED(HidlUtils::audioUsageToHal(metadata.usage, &halTrackMetadata.usage),
- result);
- CONVERT_CHECKED(HidlUtils::audioContentTypeToHal(metadata.contentType,
- &halTrackMetadata.content_type),
- result);
- if (halTracks != nullptr) {
- halTracks->push_back(std::move(halTrackMetadata));
- }
- }
- return result;
-}
-#endif // MAJOR_VERSION >= 4
-
-#if MAJOR_VERSION >= 7
-namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
-}
-
-bool audioInputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_input_flags_t* halFlags) {
- bool success = true;
- *halFlags = {};
- for (const auto& flag : flags) {
- audio_input_flags_t halFlag;
- if (!xsd::isUnknownAudioInOutFlag(flag) &&
- audio_input_flag_from_string(flag.c_str(), &halFlag)) {
- *halFlags = static_cast<audio_input_flags_t>(*halFlags | halFlag);
- } else {
- ALOGE("Unknown audio input flag \"%s\"", flag.c_str());
- success = false;
- }
- }
- return success;
-}
-
-bool audioOutputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_output_flags_t* halFlags) {
- bool success = true;
- *halFlags = {};
- for (const auto& flag : flags) {
- audio_output_flags_t halFlag;
- if (!xsd::isUnknownAudioInOutFlag(flag) &&
- audio_output_flag_from_string(flag.c_str(), &halFlag)) {
- *halFlags = static_cast<audio_output_flags_t>(*halFlags | halFlag);
- } else {
- ALOGE("Unknown audio output flag \"%s\"", flag.c_str());
- success = false;
- }
- }
- return success;
-}
-
-status_t sinkMetadataToHalV7(const SinkMetadata& sinkMetadata,
- std::vector<record_track_metadata_v7_t>* halTracks) {
- std::vector<record_track_metadata> bases;
- status_t result = sinkMetadataToHal(sinkMetadata, halTracks != nullptr ? &bases : nullptr);
- if (halTracks != nullptr) {
- halTracks->reserve(bases.size());
- }
- auto baseIter = std::make_move_iterator(bases.begin());
- for (auto& metadata : sinkMetadata.tracks) {
- record_track_metadata_v7_t halTrackMetadata;
- CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(metadata.channelMask,
- &halTrackMetadata.channel_mask),
- result);
- CONVERT_CHECKED(HidlUtils::audioTagsToHal(metadata.tags, halTrackMetadata.tags), result);
- if (halTracks != nullptr) {
- halTrackMetadata.base = std::move(*baseIter++);
- halTracks->push_back(std::move(halTrackMetadata));
- }
- }
- return result;
-}
-
-status_t sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
- std::vector<playback_track_metadata_v7_t>* halTracks) {
- std::vector<playback_track_metadata_t> bases;
- status_t result = sourceMetadataToHal(sourceMetadata, halTracks != nullptr ? &bases : nullptr);
- if (halTracks != nullptr) {
- halTracks->reserve(bases.size());
- }
- auto baseIter = std::make_move_iterator(bases.begin());
- for (auto& metadata : sourceMetadata.tracks) {
- playback_track_metadata_v7_t halTrackMetadata;
- CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(metadata.channelMask,
- &halTrackMetadata.channel_mask),
- result);
- CONVERT_CHECKED(HidlUtils::audioTagsToHal(metadata.tags, halTrackMetadata.tags), result);
- if (halTracks != nullptr) {
- halTrackMetadata.base = std::move(*baseIter++);
- halTracks->push_back(std::move(halTrackMetadata));
- }
- }
- return result;
-}
-#endif
-
-} // namespace implementation
-} // namespace CPP_VERSION
-} // namespace audio
-} // namespace hardware
-} // namespace android
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 7caed44..70a1a4d 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -17,9 +17,7 @@
#define LOG_TAG "DeviceHAL"
#include "core/default/Device.h"
-#include <HidlUtils.h>
#include "common/all-versions/default/EffectMap.h"
-#include "core/default/Conversions.h"
#include "core/default/StreamIn.h"
#include "core/default/StreamOut.h"
#include "core/default/Util.h"
@@ -33,6 +31,8 @@
#include <android/log.h>
+#include <HidlUtils.h>
+
namespace android {
namespace hardware {
namespace audio {
@@ -160,11 +160,11 @@
audio_stream_out_t* halStream;
audio_devices_t halDevice;
char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
- if (deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
+ if (CoreUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
return {Result::INVALID_ARGUMENTS, nullptr};
}
audio_output_flags_t halFlags;
- if (!audioOutputFlagsToHal(flags, &halFlags)) {
+ if (CoreUtils::audioOutputFlagsToHal(flags, &halFlags) != NO_ERROR) {
return {Result::INVALID_ARGUMENTS, nullptr};
}
ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
@@ -195,12 +195,12 @@
audio_stream_in_t* halStream;
audio_devices_t halDevice;
char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
- if (deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
+ if (CoreUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
return {Result::INVALID_ARGUMENTS, nullptr};
}
audio_input_flags_t halFlags;
audio_source_t halSource;
- if (!audioInputFlagsToHal(flags, &halFlags) ||
+ if (CoreUtils::audioInputFlagsToHal(flags, &halFlags) != NO_ERROR ||
HidlUtils::audioSourceToHal(source, &halSource) != NO_ERROR) {
return {Result::INVALID_ARGUMENTS, nullptr};
}
@@ -254,9 +254,12 @@
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
#if MAJOR_VERSION <= 6
- if (status_t status = sourceMetadataToHal(sourceMetadata, nullptr); status != NO_ERROR) {
+ if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
+ status != NO_ERROR) {
#else
- if (status_t status = sourceMetadataToHalV7(sourceMetadata, nullptr); status != NO_ERROR) {
+ if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
+ false /*ignoreNonVendorTags*/, nullptr);
+ status != NO_ERROR) {
#endif
_hidl_cb(analyzeStatus("sourceMetadataToHal", status), nullptr, AudioConfig{});
return Void();
@@ -288,9 +291,11 @@
return Void();
}
#if MAJOR_VERSION <= 6
- if (status_t status = sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
+ if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
#else
- if (status_t status = sinkMetadataToHalV7(sinkMetadata, nullptr); status != NO_ERROR) {
+ if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
+ false /*ignoreNonVendorTags*/, nullptr);
+ status != NO_ERROR) {
#endif
_hidl_cb(analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{});
return Void();
@@ -444,7 +449,7 @@
mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
microphones.resize(actual_mics);
for (size_t i = 0; i < actual_mics; ++i) {
- halToMicrophoneCharacteristics(µphones[i], mic_array[i]);
+ (void)CoreUtils::microphoneInfoFromHal(mic_array[i], µphones[i]);
}
retval = Result::OK;
}
diff --git a/audio/core/all-versions/default/ParametersUtil.cpp b/audio/core/all-versions/default/ParametersUtil.cpp
index 694eb73..4d53645 100644
--- a/audio/core/all-versions/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/ParametersUtil.cpp
@@ -15,11 +15,12 @@
*/
#include "core/default/ParametersUtil.h"
-#include "core/default/Conversions.h"
#include "core/default/Util.h"
#include <system/audio.h>
+#include <util/CoreUtils.h>
+
namespace android {
namespace hardware {
namespace audio {
@@ -153,7 +154,7 @@
Result ParametersUtil::setParam(const char* name, const DeviceAddress& address) {
audio_devices_t halDeviceType;
char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
- if (deviceAddressToHal(address, &halDeviceType, halDeviceAddress) != NO_ERROR) {
+ if (CoreUtils::deviceAddressToHal(address, &halDeviceType, halDeviceAddress) != NO_ERROR) {
return Result::INVALID_ARGUMENTS;
}
AudioParameter params{String8(halDeviceAddress)};
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index 3f8efd2..7e32573 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -19,7 +19,6 @@
#include "core/default/Stream.h"
#include "common/all-versions/HidlSupport.h"
#include "common/all-versions/default/EffectMap.h"
-#include "core/default/Conversions.h"
#include "core/default/Util.h"
#include <inttypes.h>
@@ -30,6 +29,7 @@
#include <hardware/audio_effect.h>
#include <media/AudioContainers.h>
#include <media/TypeConverter.h>
+#include <util/CoreUtils.h>
namespace android {
namespace hardware {
@@ -373,9 +373,10 @@
hidl_vec<DeviceAddress> devices;
if (retval == Result::OK) {
devices.resize(1);
- retval = Stream::analyzeStatus("get_devices",
- deviceAddressFromHal(static_cast<audio_devices_t>(halDevice),
- nullptr, &devices[0]));
+ retval = Stream::analyzeStatus(
+ "get_devices",
+ CoreUtils::deviceAddressFromHal(static_cast<audio_devices_t>(halDevice), nullptr,
+ &devices[0]));
}
_hidl_cb(retval, devices);
return Void();
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index c670a4d..599f3c3 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "StreamInHAL"
#include "core/default/StreamIn.h"
-#include "core/default/Conversions.h"
#include "core/default/Util.h"
#include "common/all-versions/HidlSupport.h"
@@ -27,6 +26,7 @@
#include <HidlUtils.h>
#include <android/log.h>
#include <hardware/audio.h>
+#include <util/CoreUtils.h>
#include <utils/Trace.h>
#include <cmath>
#include <memory>
@@ -481,13 +481,15 @@
Result StreamIn::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
std::vector<record_track_metadata> halTracks;
#if MAJOR_VERSION <= 6
- (void)sinkMetadataToHal(sinkMetadata, &halTracks);
+ (void)CoreUtils::sinkMetadataToHal(sinkMetadata, &halTracks);
#else
// Validate whether a conversion to V7 is possible. This is needed
// to have a consistent behavior of the HAL regardless of the API
// version of the legacy HAL (and also to be consistent with openInputStream).
std::vector<record_track_metadata_v7> halTracksV7;
- if (status_t status = sinkMetadataToHalV7(sinkMetadata, &halTracksV7); status == NO_ERROR) {
+ if (status_t status = CoreUtils::sinkMetadataToHalV7(
+ sinkMetadata, false /*ignoreNonVendorTags*/, &halTracksV7);
+ status == NO_ERROR) {
halTracks.reserve(halTracksV7.size());
for (auto metadata_v7 : halTracksV7) {
halTracks.push_back(std::move(metadata_v7.base));
@@ -507,7 +509,9 @@
#if MAJOR_VERSION >= 7
Result StreamIn::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
std::vector<record_track_metadata_v7> halTracks;
- if (status_t status = sinkMetadataToHalV7(sinkMetadata, &halTracks); status != NO_ERROR) {
+ if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
+ false /*ignoreNonVendorTags*/, &halTracks);
+ status != NO_ERROR) {
return Stream::analyzeStatus("sinkMetadataToHal", status);
}
const sink_metadata_v7_t halMetadata = {
@@ -553,7 +557,7 @@
mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
microphones.resize(actual_mics);
for (size_t i = 0; i < actual_mics; ++i) {
- halToMicrophoneCharacteristics(µphones[i], mic_array[i]);
+ (void)CoreUtils::microphoneInfoFromHal(mic_array[i], µphones[i]);
}
retval = Result::OK;
}
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index c2ad720..5e4dd2a 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "StreamOutHAL"
#include "core/default/StreamOut.h"
-#include "core/default/Conversions.h"
#include "core/default/Util.h"
//#define LOG_NDEBUG 0
@@ -30,6 +29,7 @@
#include <HidlUtils.h>
#include <android/log.h>
#include <hardware/audio.h>
+#include <util/CoreUtils.h>
#include <utils/Trace.h>
namespace android {
@@ -589,13 +589,15 @@
Result StreamOut::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
std::vector<playback_track_metadata_t> halTracks;
#if MAJOR_VERSION <= 6
- (void)sourceMetadataToHal(sourceMetadata, &halTracks);
+ (void)CoreUtils::sourceMetadataToHal(sourceMetadata, &halTracks);
#else
// Validate whether a conversion to V7 is possible. This is needed
// to have a consistent behavior of the HAL regardless of the API
// version of the legacy HAL (and also to be consistent with openOutputStream).
std::vector<playback_track_metadata_v7> halTracksV7;
- if (status_t status = sourceMetadataToHalV7(sourceMetadata, &halTracksV7); status == NO_ERROR) {
+ if (status_t status = CoreUtils::sourceMetadataToHalV7(
+ sourceMetadata, false /*ignoreNonVendorTags*/, &halTracksV7);
+ status == NO_ERROR) {
halTracks.reserve(halTracksV7.size());
for (auto metadata_v7 : halTracksV7) {
halTracks.push_back(std::move(metadata_v7.base));
@@ -615,7 +617,9 @@
#if MAJOR_VERSION >= 7
Result StreamOut::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
std::vector<playback_track_metadata_v7> halTracks;
- if (status_t status = sourceMetadataToHalV7(sourceMetadata, &halTracks); status != NO_ERROR) {
+ if (status_t status = CoreUtils::sourceMetadataToHalV7(
+ sourceMetadata, false /*ignoreNonVendorTags*/, &halTracks);
+ status != NO_ERROR) {
return Stream::analyzeStatus("sourceMetadataToHal", status);
}
const source_metadata_v7_t halMetadata = {
diff --git a/audio/core/all-versions/default/TEST_MAPPING b/audio/core/all-versions/default/TEST_MAPPING
new file mode 100644
index 0000000..d53c97a
--- /dev/null
+++ b/audio/core/all-versions/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "android.hardware.audio@7.0-util_tests"
+ }
+ ]
+}
diff --git a/audio/core/all-versions/default/include/core/default/Conversions.h b/audio/core/all-versions/default/include/core/default/Conversions.h
deleted file mode 100644
index 61720d5..0000000
--- a/audio/core/all-versions/default/include/core/default/Conversions.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
-#define ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
-
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-
-#include <string>
-
-#include <system/audio.h>
-
-#include <VersionUtils.h>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
-
-status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
- char* halDeviceAddress);
-status_t deviceAddressFromHal(audio_devices_t halDeviceType, const char* halDeviceAddress,
- DeviceAddress* device);
-
-#if MAJOR_VERSION >= 4
-bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
- const struct audio_microphone_characteristic_t& src);
-status_t sinkMetadataToHal(const SinkMetadata& sinkMetadata,
- std::vector<record_track_metadata>* halTracks);
-status_t sourceMetadataToHal(const SourceMetadata& sourceMetadata,
- std::vector<playback_track_metadata_t>* halTracks);
-#endif
-
-#if MAJOR_VERSION <= 6
-using AudioInputFlags =
- ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
-using AudioOutputFlags =
- ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
-
-inline bool audioInputFlagsToHal(AudioInputFlags flags, audio_input_flags_t* halFlags) {
- *halFlags = static_cast<audio_input_flags_t>(flags);
- return true;
-}
-
-inline bool audioOutputFlagsToHal(AudioOutputFlags flags, audio_output_flags_t* halFlags) {
- *halFlags = static_cast<audio_output_flags_t>(flags);
- return true;
-}
-#else
-bool audioInputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_input_flags_t* halFlags);
-bool audioOutputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_output_flags_t* halFlags);
-// Overloading isn't convenient when passing a nullptr.
-status_t sinkMetadataToHalV7(const SinkMetadata& sinkMetadata,
- std::vector<record_track_metadata_v7_t>* halTracks);
-status_t sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
- std::vector<playback_track_metadata_v7_t>* halTracks);
-#endif
-
-} // namespace implementation
-} // namespace CPP_VERSION
-} // namespace audio
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
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 2a4d226..5851fc9 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -31,6 +31,7 @@
#include <hidl/MQDescriptor.h>
#include <VersionUtils.h>
+#include <util/CoreUtils.h>
namespace android {
namespace hardware {
@@ -43,17 +44,10 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-#if MAJOR_VERSION <= 6
-using AudioInputFlags =
- ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
-using AudioOutputFlags =
- ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
-#else
-using AudioInputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
-using AudioOutputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
-#endif
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
+using AudioInputFlags = CoreUtils::AudioInputFlags;
+using AudioOutputFlags = CoreUtils::AudioOutputFlags;
struct Device : public IDevice, public ParametersUtil {
explicit Device(audio_hw_device_t* device);
diff --git a/audio/core/all-versions/default/util/Android.bp b/audio/core/all-versions/default/util/Android.bp
new file mode 100644
index 0000000..447184b
--- /dev/null
+++ b/audio/core/all-versions/default/util/Android.bp
@@ -0,0 +1,139 @@
+cc_defaults {
+ name: "android.hardware.audio-util_default",
+ defaults: ["hidl_defaults"],
+
+ vendor_available: true,
+
+ export_include_dirs: ["include"],
+
+ srcs: [
+ "CoreUtils.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libhidlbase",
+ "android.hardware.audio.common-util",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.audio.common-util",
+ ],
+
+ header_libs: [
+ "libaudio_system_headers",
+ "libhardware_headers",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio@2.0-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@2.0",
+ "android.hardware.audio.common@2.0-util",
+ "android.hardware.audio@2.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=2",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio@4.0-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@4.0",
+ "android.hardware.audio.common@4.0-util",
+ "android.hardware.audio@4.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=4",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio@5.0-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@5.0",
+ "android.hardware.audio.common@5.0-util",
+ "android.hardware.audio@5.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=5",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio@6.0-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@6.0",
+ "android.hardware.audio.common@6.0-util",
+ "android.hardware.audio@6.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=6",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library {
+ name: "android.hardware.audio@7.0-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio@7.0",
+ "libbase",
+ "libxml2",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of conversion utilities.
+cc_test {
+ name: "android.hardware.audio@7.0-util_tests",
+ defaults: ["android.hardware.audio-util_default"],
+
+ srcs: ["tests/coreutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.
+ static_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio@7.0",
+ "android.hardware.audio@7.0-util",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp
new file mode 100644
index 0000000..14f76f3
--- /dev/null
+++ b/audio/core/all-versions/default/util/CoreUtils.cpp
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if MAJOR_VERSION >= 7
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#endif
+#include <HidlUtils.h>
+#include <log/log.h>
+
+#include "util/CoreUtils.h"
+
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+#if MAJOR_VERSION >= 7
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+#endif
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace CPP_VERSION {
+namespace implementation {
+
+#define CONVERT_CHECKED(expr, result) \
+ if (status_t status = (expr); status != NO_ERROR) { \
+ result = status; \
+ }
+
+status_t CoreUtils::deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
+ char* halDeviceAddress) {
+#if MAJOR_VERSION >= 5
+ return HidlUtils::deviceAddressToHal(device, halDeviceType, halDeviceAddress);
+#else
+ return HidlUtils::deviceAddressToHalImpl(device, halDeviceType, halDeviceAddress);
+#endif
+}
+
+status_t CoreUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
+ const char* halDeviceAddress, DeviceAddress* device) {
+#if MAJOR_VERSION >= 5
+ return HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, device);
+#else
+ return HidlUtils::deviceAddressFromHalImpl(halDeviceType, halDeviceAddress, device);
+#endif
+}
+
+#if MAJOR_VERSION >= 4
+status_t CoreUtils::microphoneInfoFromHal(
+ const struct audio_microphone_characteristic_t& halMicInfo, MicrophoneInfo* micInfo) {
+ status_t result = NO_ERROR;
+ micInfo->deviceId = halMicInfo.device_id;
+ CONVERT_CHECKED(
+ deviceAddressFromHal(halMicInfo.device, halMicInfo.address, &micInfo->deviceAddress),
+ result);
+ size_t chCount;
+ for (chCount = 0; chCount < AUDIO_CHANNEL_COUNT_MAX; ++chCount) {
+ if (halMicInfo.channel_mapping[chCount] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
+ break;
+ }
+ }
+ micInfo->channelMapping.resize(chCount);
+ for (size_t ch = 0; ch < micInfo->channelMapping.size(); ch++) {
+ micInfo->channelMapping[ch] = AudioMicrophoneChannelMapping(halMicInfo.channel_mapping[ch]);
+ }
+ micInfo->location = AudioMicrophoneLocation(halMicInfo.location);
+ micInfo->group = AudioMicrophoneGroup(halMicInfo.group);
+ micInfo->indexInTheGroup = static_cast<uint32_t>(halMicInfo.index_in_the_group);
+ micInfo->sensitivity = halMicInfo.sensitivity;
+ micInfo->maxSpl = halMicInfo.max_spl;
+ micInfo->minSpl = halMicInfo.min_spl;
+ micInfo->directionality = AudioMicrophoneDirectionality(halMicInfo.directionality);
+ micInfo->frequencyResponse.resize(halMicInfo.num_frequency_responses);
+ for (size_t k = 0; k < halMicInfo.num_frequency_responses; k++) {
+ micInfo->frequencyResponse[k].frequency = halMicInfo.frequency_responses[0][k];
+ micInfo->frequencyResponse[k].level = halMicInfo.frequency_responses[1][k];
+ }
+ micInfo->position.x = halMicInfo.geometric_location.x;
+ micInfo->position.y = halMicInfo.geometric_location.y;
+ micInfo->position.z = halMicInfo.geometric_location.z;
+ micInfo->orientation.x = halMicInfo.orientation.x;
+ micInfo->orientation.y = halMicInfo.orientation.y;
+ micInfo->orientation.z = halMicInfo.orientation.z;
+ return result;
+}
+
+status_t CoreUtils::microphoneInfoToHal(const MicrophoneInfo& micInfo,
+ audio_microphone_characteristic_t* halMicInfo) {
+ status_t result = NO_ERROR;
+ strncpy(halMicInfo->device_id, micInfo.deviceId.c_str(), AUDIO_MICROPHONE_ID_MAX_LEN);
+ halMicInfo->device_id[AUDIO_MICROPHONE_ID_MAX_LEN - 1] = '\0';
+ if (micInfo.deviceId.size() >= AUDIO_MICROPHONE_ID_MAX_LEN) {
+ ALOGE("HIDL MicrophoneInfo device ID is too long: %zu", micInfo.deviceId.size());
+ result = BAD_VALUE;
+ }
+ CONVERT_CHECKED(
+ deviceAddressToHal(micInfo.deviceAddress, &halMicInfo->device, halMicInfo->address),
+ result);
+ if (micInfo.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
+ ALOGE("HIDL MicrophoneInfo has too many channelMapping elements: %zu",
+ micInfo.channelMapping.size());
+ result = BAD_VALUE;
+ }
+ size_t ch;
+ for (ch = 0; ch < micInfo.channelMapping.size() && ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+ halMicInfo->channel_mapping[ch] =
+ static_cast<audio_microphone_channel_mapping_t>(micInfo.channelMapping[ch]);
+ }
+ for (; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+ halMicInfo->channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ }
+ halMicInfo->location = static_cast<audio_microphone_location_t>(micInfo.location);
+ halMicInfo->group = static_cast<audio_microphone_group_t>(micInfo.group);
+ halMicInfo->index_in_the_group = static_cast<unsigned int>(micInfo.indexInTheGroup);
+ halMicInfo->sensitivity = micInfo.sensitivity;
+ halMicInfo->max_spl = micInfo.maxSpl;
+ halMicInfo->min_spl = micInfo.minSpl;
+ halMicInfo->directionality =
+ static_cast<audio_microphone_directionality_t>(micInfo.directionality);
+ halMicInfo->num_frequency_responses =
+ static_cast<unsigned int>(micInfo.frequencyResponse.size());
+ if (halMicInfo->num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("HIDL MicrophoneInfo has too many frequency responses: %u",
+ halMicInfo->num_frequency_responses);
+ halMicInfo->num_frequency_responses = AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES;
+ result = BAD_VALUE;
+ }
+ for (size_t k = 0; k < halMicInfo->num_frequency_responses; k++) {
+ halMicInfo->frequency_responses[0][k] = micInfo.frequencyResponse[k].frequency;
+ halMicInfo->frequency_responses[1][k] = micInfo.frequencyResponse[k].level;
+ }
+ halMicInfo->geometric_location.x = micInfo.position.x;
+ halMicInfo->geometric_location.y = micInfo.position.y;
+ halMicInfo->geometric_location.z = micInfo.position.z;
+ halMicInfo->orientation.x = micInfo.orientation.x;
+ halMicInfo->orientation.y = micInfo.orientation.y;
+ halMicInfo->orientation.z = micInfo.orientation.z;
+ return result;
+}
+
+status_t CoreUtils::sinkMetadataFromHal(const std::vector<record_track_metadata_t>& halTracks,
+ SinkMetadata* sinkMetadata) {
+ status_t result = NO_ERROR;
+ sinkMetadata->tracks.resize(halTracks.size());
+ for (size_t i = 0; i < sinkMetadata->tracks.size(); ++i) {
+ const auto& halTrackMetadata = halTracks[i];
+ RecordTrackMetadata trackMetadata{};
+ CONVERT_CHECKED(
+ HidlUtils::audioSourceFromHal(halTrackMetadata.source, &trackMetadata.source),
+ result);
+ trackMetadata.gain = halTrackMetadata.gain;
+#if MAJOR_VERSION >= 5
+ if (halTrackMetadata.dest_device != AUDIO_DEVICE_NONE) {
+ DeviceAddress address;
+ if (status_t status =
+ deviceAddressFromHal(halTrackMetadata.dest_device,
+ halTrackMetadata.dest_device_address, &address);
+ status == NO_ERROR) {
+ trackMetadata.destination.device(std::move(address));
+ } else {
+ result = status;
+ }
+ }
+#if MAJOR_VERSION >= 7
+ trackMetadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+#endif
+#endif // MAJOR_VERSION >= 5
+ sinkMetadata->tracks[i] = std::move(trackMetadata);
+ }
+ return result;
+}
+
+status_t CoreUtils::sinkMetadataFromHalV7(const std::vector<record_track_metadata_v7_t>& halTracks,
+ bool ignoreNonVendorTags, SinkMetadata* sinkMetadata) {
+ std::vector<record_track_metadata_t> bases;
+ bases.reserve(halTracks.size());
+ std::transform(halTracks.begin(), halTracks.end(), std::back_inserter(bases),
+ [](const record_track_metadata_v7_t& src) -> record_track_metadata_t {
+ record_track_metadata_t result;
+ record_track_metadata_from_v7(&result, &src);
+ return result;
+ });
+ status_t result = sinkMetadataFromHal(bases, sinkMetadata);
+#if MAJOR_VERSION >= 7
+ for (size_t i = 0; i < halTracks.size(); ++i) {
+ auto& trackMetadata = sinkMetadata->tracks[i];
+ const auto& halTrackMetadata = halTracks[i];
+ CONVERT_CHECKED(
+ HidlUtils::audioChannelMaskFromHal(halTrackMetadata.channel_mask, true /*isInput*/,
+ &trackMetadata.channelMask),
+ result);
+ std::vector<std::string> strTags = HidlUtils::splitAudioTags(halTrackMetadata.tags);
+ if (ignoreNonVendorTags) {
+ strTags = HidlUtils::filterOutNonVendorTags(strTags);
+ }
+ CONVERT_CHECKED(HidlUtils::audioTagsFromHal(strTags, &trackMetadata.tags), result);
+ }
+#else
+ (void)ignoreNonVendorTags;
+#endif
+ return result;
+}
+
+status_t CoreUtils::sinkMetadataToHal(const SinkMetadata& sinkMetadata,
+ std::vector<record_track_metadata_t>* halTracks) {
+ status_t result = NO_ERROR;
+ if (halTracks != nullptr) {
+ halTracks->reserve(sinkMetadata.tracks.size());
+ }
+ for (auto& trackMetadata : sinkMetadata.tracks) {
+ record_track_metadata halTrackMetadata{.gain = trackMetadata.gain};
+ CONVERT_CHECKED(HidlUtils::audioSourceToHal(trackMetadata.source, &halTrackMetadata.source),
+ result);
+#if MAJOR_VERSION >= 5
+ if (trackMetadata.destination.getDiscriminator() ==
+ RecordTrackMetadata::Destination::hidl_discriminator::device) {
+ CONVERT_CHECKED(deviceAddressToHal(trackMetadata.destination.device(),
+ &halTrackMetadata.dest_device,
+ halTrackMetadata.dest_device_address),
+ result);
+ }
+#endif
+ if (halTracks != nullptr) {
+ halTracks->push_back(std::move(halTrackMetadata));
+ }
+ }
+ return result;
+}
+
+status_t CoreUtils::sinkMetadataToHalV7(const SinkMetadata& sinkMetadata, bool ignoreNonVendorTags,
+ std::vector<record_track_metadata_v7_t>* halTracks) {
+ std::vector<record_track_metadata> bases;
+ status_t result = sinkMetadataToHal(sinkMetadata, halTracks != nullptr ? &bases : nullptr);
+ if (halTracks != nullptr) {
+ halTracks->reserve(sinkMetadata.tracks.size());
+ }
+ for (size_t i = 0; i < sinkMetadata.tracks.size(); ++i) {
+ record_track_metadata_v7_t halTrackMetadata;
+ if (halTracks != nullptr) {
+ record_track_metadata_to_v7(&halTrackMetadata, &bases[i]);
+ }
+#if MAJOR_VERSION >= 7
+ const auto& trackMetadata = sinkMetadata.tracks[i];
+ CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
+ &halTrackMetadata.channel_mask),
+ result);
+ if (ignoreNonVendorTags) {
+ CONVERT_CHECKED(
+ HidlUtils::audioTagsToHal(HidlUtils::filterOutNonVendorTags(trackMetadata.tags),
+ halTrackMetadata.tags),
+ result);
+ } else {
+ CONVERT_CHECKED(HidlUtils::audioTagsToHal(trackMetadata.tags, halTrackMetadata.tags),
+ result);
+ }
+#else
+ (void)ignoreNonVendorTags;
+#endif
+ if (halTracks != nullptr) {
+ halTracks->push_back(std::move(halTrackMetadata));
+ }
+ }
+ return result;
+}
+
+status_t CoreUtils::sourceMetadataFromHal(const std::vector<playback_track_metadata_t>& halTracks,
+ SourceMetadata* sourceMetadata) {
+ status_t result = NO_ERROR;
+ sourceMetadata->tracks.resize(halTracks.size());
+ for (size_t i = 0; i < sourceMetadata->tracks.size(); ++i) {
+ const auto& halTrackMetadata = halTracks[i];
+ PlaybackTrackMetadata trackMetadata{};
+ CONVERT_CHECKED(HidlUtils::audioUsageFromHal(halTrackMetadata.usage, &trackMetadata.usage),
+ result);
+ CONVERT_CHECKED(HidlUtils::audioContentTypeFromHal(halTrackMetadata.content_type,
+ &trackMetadata.contentType),
+ result);
+ trackMetadata.gain = halTrackMetadata.gain;
+#if MAJOR_VERSION >= 7
+ trackMetadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+#endif
+ sourceMetadata->tracks[i] = std::move(trackMetadata);
+ }
+ return result;
+}
+
+status_t CoreUtils::sourceMetadataFromHalV7(
+ const std::vector<playback_track_metadata_v7_t>& halTracks, bool ignoreNonVendorTags,
+ SourceMetadata* sourceMetadata) {
+ std::vector<playback_track_metadata_t> bases;
+ bases.reserve(halTracks.size());
+ std::transform(halTracks.begin(), halTracks.end(), std::back_inserter(bases),
+ [](const playback_track_metadata_v7_t& src) -> playback_track_metadata_t {
+ playback_track_metadata_t result;
+ playback_track_metadata_from_v7(&result, &src);
+ return result;
+ });
+ status_t result = sourceMetadataFromHal(bases, sourceMetadata);
+#if MAJOR_VERSION >= 7
+ for (size_t i = 0; i < halTracks.size(); ++i) {
+ auto& trackMetadata = sourceMetadata->tracks[i];
+ const auto& halTrackMetadata = halTracks[i];
+ CONVERT_CHECKED(
+ HidlUtils::audioChannelMaskFromHal(halTrackMetadata.channel_mask, false /*isInput*/,
+ &trackMetadata.channelMask),
+ result);
+ std::vector<std::string> strTags = HidlUtils::splitAudioTags(halTrackMetadata.tags);
+ if (ignoreNonVendorTags) {
+ strTags = HidlUtils::filterOutNonVendorTags(strTags);
+ }
+ CONVERT_CHECKED(HidlUtils::audioTagsFromHal(strTags, &trackMetadata.tags), result);
+ }
+#else
+ (void)ignoreNonVendorTags;
+#endif
+ return result;
+}
+
+status_t CoreUtils::sourceMetadataToHal(const SourceMetadata& sourceMetadata,
+ std::vector<playback_track_metadata_t>* halTracks) {
+ status_t result = NO_ERROR;
+ if (halTracks != nullptr) {
+ halTracks->reserve(sourceMetadata.tracks.size());
+ }
+ for (auto& trackMetadata : sourceMetadata.tracks) {
+ playback_track_metadata_t halTrackMetadata{.gain = trackMetadata.gain};
+ CONVERT_CHECKED(HidlUtils::audioUsageToHal(trackMetadata.usage, &halTrackMetadata.usage),
+ result);
+ CONVERT_CHECKED(HidlUtils::audioContentTypeToHal(trackMetadata.contentType,
+ &halTrackMetadata.content_type),
+ result);
+ if (halTracks != nullptr) {
+ halTracks->push_back(std::move(halTrackMetadata));
+ }
+ }
+ return result;
+}
+
+status_t CoreUtils::sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
+ bool ignoreNonVendorTags,
+ std::vector<playback_track_metadata_v7_t>* halTracks) {
+ std::vector<playback_track_metadata_t> bases;
+ status_t result = sourceMetadataToHal(sourceMetadata, halTracks != nullptr ? &bases : nullptr);
+ if (halTracks != nullptr) {
+ halTracks->reserve(sourceMetadata.tracks.size());
+ }
+ for (size_t i = 0; i < sourceMetadata.tracks.size(); ++i) {
+ playback_track_metadata_v7_t halTrackMetadata;
+ if (halTracks != nullptr) {
+ playback_track_metadata_to_v7(&halTrackMetadata, &bases[i]);
+ }
+#if MAJOR_VERSION >= 7
+ const auto& trackMetadata = sourceMetadata.tracks[i];
+ CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
+ &halTrackMetadata.channel_mask),
+ result);
+ if (ignoreNonVendorTags) {
+ CONVERT_CHECKED(
+ HidlUtils::audioTagsToHal(HidlUtils::filterOutNonVendorTags(trackMetadata.tags),
+ halTrackMetadata.tags),
+ result);
+ } else {
+ CONVERT_CHECKED(HidlUtils::audioTagsToHal(trackMetadata.tags, halTrackMetadata.tags),
+ result);
+ }
+#else
+ (void)ignoreNonVendorTags;
+#endif
+ if (halTracks != nullptr) {
+ halTracks->push_back(std::move(halTrackMetadata));
+ }
+ }
+ return result;
+}
+#endif // MAJOR_VERSION >= 4
+
+#if MAJOR_VERSION >= 7
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+status_t CoreUtils::audioInputFlagsFromHal(audio_input_flags_t halFlagMask,
+ AudioInputFlags* flags) {
+ status_t status = NO_ERROR;
+ std::vector<AudioInOutFlag> result;
+ for (uint32_t bit = 0; halFlagMask != 0 && bit < sizeof(audio_input_flags_t) * 8; ++bit) {
+ audio_input_flags_t flag = static_cast<audio_input_flags_t>(1u << bit);
+ if ((flag & halFlagMask) == flag) {
+ AudioInOutFlag flagStr = audio_input_flag_to_string(flag);
+ if (!flagStr.empty() && !xsd::isUnknownAudioInOutFlag(flagStr)) {
+ result.push_back(flagStr);
+ } else {
+ ALOGE("Unknown audio input flag value 0x%X", flag);
+ status = BAD_VALUE;
+ }
+ halFlagMask = static_cast<audio_input_flags_t>(halFlagMask & ~flag);
+ }
+ }
+ *flags = result;
+ return status;
+}
+
+status_t CoreUtils::audioInputFlagsToHal(const AudioInputFlags& flags,
+ audio_input_flags_t* halFlagMask) {
+ status_t status = NO_ERROR;
+ *halFlagMask = {};
+ for (const auto& flag : flags) {
+ audio_input_flags_t halFlag;
+ if (!xsd::isUnknownAudioInOutFlag(flag) &&
+ audio_input_flag_from_string(flag.c_str(), &halFlag)) {
+ *halFlagMask = static_cast<audio_input_flags_t>(*halFlagMask | halFlag);
+ } else {
+ ALOGE("Unknown audio input flag \"%s\"", flag.c_str());
+ status = BAD_VALUE;
+ }
+ }
+ return status;
+}
+
+status_t CoreUtils::audioOutputFlagsFromHal(audio_output_flags_t halFlagMask,
+ AudioOutputFlags* flags) {
+ status_t status = NO_ERROR;
+ std::vector<AudioInOutFlag> result;
+ for (uint32_t bit = 0; halFlagMask != 0 && bit < sizeof(audio_output_flags_t) * 8; ++bit) {
+ audio_output_flags_t flag = static_cast<audio_output_flags_t>(1u << bit);
+ if ((flag & halFlagMask) == flag) {
+ AudioInOutFlag flagStr = audio_output_flag_to_string(flag);
+ if (!flagStr.empty() && !xsd::isUnknownAudioInOutFlag(flagStr)) {
+ result.push_back(flagStr);
+ } else {
+ ALOGE("Unknown audio output flag value 0x%X", flag);
+ status = BAD_VALUE;
+ }
+ halFlagMask = static_cast<audio_output_flags_t>(halFlagMask & ~flag);
+ }
+ }
+ *flags = result;
+ return status;
+}
+
+status_t CoreUtils::audioOutputFlagsToHal(const AudioOutputFlags& flags,
+ audio_output_flags_t* halFlagMask) {
+ status_t status = NO_ERROR;
+ *halFlagMask = {};
+ for (const auto& flag : flags) {
+ audio_output_flags_t halFlag;
+ if (!xsd::isUnknownAudioInOutFlag(flag) &&
+ audio_output_flag_from_string(flag.c_str(), &halFlag)) {
+ *halFlagMask = static_cast<audio_output_flags_t>(*halFlagMask | halFlag);
+ } else {
+ ALOGE("Unknown audio output flag \"%s\"", flag.c_str());
+ status = BAD_VALUE;
+ }
+ }
+ return status;
+}
+#endif
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/core/all-versions/default/util/include/util/CoreUtils.h b/audio/core/all-versions/default/util/include/util/CoreUtils.h
new file mode 100644
index 0000000..1e5272a
--- /dev/null
+++ b/audio/core/all-versions/default/util/include/util/CoreUtils.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// clang-format off
+#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+// clang-format off
+
+#include <vector>
+
+#include <system/audio.h>
+
+#include <common/all-versions/VersionUtils.h>
+#include <VersionUtils.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace CPP_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::utils::EnumBitfield;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+
+struct CoreUtils {
+ // Note: the converters for DeviceAddress have to be in CoreUtils for HAL V4
+ // because DeviceAddress used to be defined in the core HAL. For V5 and above
+ // these functions simply delegate to HidlUtils.
+ static status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
+ char* halDeviceAddress);
+ static status_t deviceAddressFromHal(audio_devices_t halDeviceType, const char* halDeviceAddress,
+ DeviceAddress* device);
+#if MAJOR_VERSION >= 4
+ static status_t microphoneInfoFromHal(const struct audio_microphone_characteristic_t& halMicInfo,
+ MicrophoneInfo* micInfo);
+ static status_t microphoneInfoToHal(const MicrophoneInfo& micInfo, audio_microphone_characteristic_t* halMicInfo);
+ // Note: {Sink|Source}Metadata types are defined in 'common' (since V5), so they can be used
+ // by the BT HAL. However, the converters are defined here, not in HidlUtils to avoid adding
+ // conditionals to handle V4. The converters are only used by 'core' HAL anyways.
+ static status_t sinkMetadataFromHal(const std::vector<record_track_metadata_t>& halTracks,
+ SinkMetadata* sinkMetadata);
+ static status_t sinkMetadataFromHalV7(const std::vector<record_track_metadata_v7_t>& halTracks,
+ bool ignoreNonVendorTags, SinkMetadata* sinkMetadata);
+ static status_t sinkMetadataToHal(const SinkMetadata& sinkMetadata,
+ std::vector<record_track_metadata_t>* halTracks);
+ static status_t sinkMetadataToHalV7(const SinkMetadata& sinkMetadata, bool ignoreNonVendorTags,
+ std::vector<record_track_metadata_v7_t>* halTracks);
+ static status_t sourceMetadataFromHal(const std::vector<playback_track_metadata_t>& halTracks,
+ SourceMetadata* sourceMetadata);
+ static status_t sourceMetadataFromHalV7(const std::vector<playback_track_metadata_v7_t>& halTracks,
+ bool ignoreNonVendorTags, SourceMetadata* sourceMetadata);
+ static status_t sourceMetadataToHal(const SourceMetadata& sourceMetadata,
+ std::vector<playback_track_metadata_t>* halTracks);
+ static status_t sourceMetadataToHalV7(const SourceMetadata& sourceMetadata, bool ignoreNonVendorTags,
+ std::vector<playback_track_metadata_v7_t>* halTracks);
+#endif
+
+#if MAJOR_VERSION <= 6
+ using AudioInputFlags =
+ ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
+ using AudioOutputFlags =
+ ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
+ static inline status_t audioInputFlagsFromHal(audio_input_flags_t halFlagMask, AudioInputFlags* flags) {
+ *flags = EnumBitfield<AudioInputFlag>(halFlagMask);
+ return NO_ERROR;
+ }
+ static inline status_t audioInputFlagsToHal(AudioInputFlags flags, audio_input_flags_t* halFlagMask) {
+ *halFlagMask = static_cast<audio_input_flags_t>(flags);
+ return NO_ERROR;
+ }
+ static inline status_t audioOutputFlagsFromHal(audio_output_flags_t halFlagMask, AudioOutputFlags* flags) {
+ *flags = EnumBitfield<AudioOutputFlag>(halFlagMask);
+ return NO_ERROR;
+ }
+ static inline status_t audioOutputFlagsToHal(AudioOutputFlags flags, audio_output_flags_t* halFlagMask) {
+ *halFlagMask = static_cast<audio_output_flags_t>(flags);
+ return NO_ERROR;
+ }
+#else
+ using AudioInputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
+ using AudioOutputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
+ static status_t audioInputFlagsFromHal(audio_input_flags_t halFlagMask, AudioInputFlags* flags);
+ static status_t audioInputFlagsToHal(const AudioInputFlags& flags, audio_input_flags_t* halFlagMask);
+ static status_t audioOutputFlagsFromHal(audio_output_flags_t halFlagMask, AudioOutputFlags* flags);
+ static status_t audioOutputFlagsToHal(const AudioOutputFlags& flags, audio_output_flags_t* halFlagMask);
+#endif
+
+};
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
new file mode 100644
index 0000000..0c18482
--- /dev/null
+++ b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "CoreUtils_Test"
+#include <log/log.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <system/audio.h>
+#include <util/CoreUtils.h>
+#include <xsdc/XsdcSupport.h>
+
+using namespace android;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
+static constexpr audio_content_type_t kInvalidHalContentType =
+ static_cast<audio_content_type_t>(0xFFFFFFFFU);
+static constexpr audio_devices_t kInvalidHalDevice = static_cast<audio_devices_t>(0xFFFFFFFFU);
+static constexpr audio_input_flags_t kInvalidInputFlags =
+ static_cast<audio_input_flags_t>(0xFFFFFFFFU);
+static constexpr audio_output_flags_t kInvalidOutputFlags =
+ static_cast<audio_output_flags_t>(0xFFFFFFFFU);
+// AUDIO_SOURCE_INVALID is framework-only.
+static constexpr audio_source_t kInvalidHalSource = static_cast<audio_source_t>(-1);
+static constexpr audio_usage_t kInvalidHalUsage = static_cast<audio_usage_t>(0xFFFFFFFFU);
+
+static bool isInputFlag(xsd::AudioInOutFlag flag) {
+ return toString(flag).find("_INPUT_FLAG_") != std::string::npos;
+}
+
+static bool isOutputFlag(xsd::AudioInOutFlag flag) {
+ return toString(flag).find("_OUTPUT_FLAG_") != std::string::npos;
+}
+
+TEST(CoreUtils, ConvertInvalidInputFlagMask) {
+ CoreUtils::AudioInputFlags invalid;
+ EXPECT_EQ(BAD_VALUE, CoreUtils::audioInputFlagsFromHal(kInvalidInputFlags, &invalid));
+ audio_input_flags_t halInvalid;
+ invalid.resize(1);
+ invalid[0] = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::audioInputFlagsToHal(invalid, &halInvalid));
+}
+
+TEST(CoreUtils, ConvertInputFlagMask) {
+ CoreUtils::AudioInputFlags emptyInputFlags;
+ audio_input_flags_t halEmptyInputFlags;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioInputFlagsToHal(emptyInputFlags, &halEmptyInputFlags));
+ EXPECT_EQ(AUDIO_INPUT_FLAG_NONE, halEmptyInputFlags);
+ CoreUtils::AudioInputFlags emptyInputFlagsBack;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::audioInputFlagsFromHal(halEmptyInputFlags, &emptyInputFlagsBack));
+ EXPECT_EQ(emptyInputFlags, emptyInputFlagsBack);
+ CoreUtils::AudioInputFlags emptyInputFlagsFromNone;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::audioInputFlagsFromHal(AUDIO_INPUT_FLAG_NONE, &emptyInputFlagsFromNone));
+ EXPECT_EQ(emptyInputFlags, emptyInputFlagsFromNone);
+
+ std::vector<std::string> allEnumValues;
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioInOutFlag>{}) {
+ if (isInputFlag(enumVal)) {
+ allEnumValues.push_back(toString(enumVal));
+ }
+ }
+ CoreUtils::AudioInputFlags allInputFlags;
+ allInputFlags.resize(allEnumValues.size());
+ for (size_t i = 0; i < allEnumValues.size(); ++i) {
+ allInputFlags[i] = allEnumValues[i];
+ }
+ audio_input_flags_t halAllInputFlags;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioInputFlagsToHal(allInputFlags, &halAllInputFlags));
+ CoreUtils::AudioInputFlags allInputFlagsBack;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioInputFlagsFromHal(halAllInputFlags, &allInputFlagsBack));
+ EXPECT_EQ(allInputFlags, allInputFlagsBack);
+}
+
+TEST(CoreUtils, ConvertInvalidOutputFlagMask) {
+ CoreUtils::AudioOutputFlags invalid;
+ EXPECT_EQ(BAD_VALUE, CoreUtils::audioOutputFlagsFromHal(kInvalidOutputFlags, &invalid));
+ audio_output_flags_t halInvalid;
+ invalid.resize(1);
+ invalid[0] = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::audioOutputFlagsToHal(invalid, &halInvalid));
+}
+
+TEST(CoreUtils, ConvertOutputFlagMask) {
+ CoreUtils::AudioOutputFlags emptyOutputFlags;
+ audio_output_flags_t halEmptyOutputFlags;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsToHal(emptyOutputFlags, &halEmptyOutputFlags));
+ EXPECT_EQ(AUDIO_OUTPUT_FLAG_NONE, halEmptyOutputFlags);
+ CoreUtils::AudioOutputFlags emptyOutputFlagsBack;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::audioOutputFlagsFromHal(halEmptyOutputFlags, &emptyOutputFlagsBack));
+ EXPECT_EQ(emptyOutputFlags, emptyOutputFlagsBack);
+ CoreUtils::AudioOutputFlags emptyOutputFlagsFromNone;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsFromHal(AUDIO_OUTPUT_FLAG_NONE,
+ &emptyOutputFlagsFromNone));
+ EXPECT_EQ(emptyOutputFlags, emptyOutputFlagsFromNone);
+
+ std::vector<std::string> allEnumValues;
+ for (const auto enumVal : xsdc_enum_range<xsd::AudioInOutFlag>{}) {
+ if (isOutputFlag(enumVal)) {
+ allEnumValues.push_back(toString(enumVal));
+ }
+ }
+ CoreUtils::AudioOutputFlags allOutputFlags;
+ allOutputFlags.resize(allEnumValues.size());
+ for (size_t i = 0; i < allEnumValues.size(); ++i) {
+ allOutputFlags[i] = allEnumValues[i];
+ }
+ audio_output_flags_t halAllOutputFlags;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsToHal(allOutputFlags, &halAllOutputFlags));
+ CoreUtils::AudioOutputFlags allOutputFlagsBack;
+ EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsFromHal(halAllOutputFlags, &allOutputFlagsBack));
+ EXPECT_EQ(allOutputFlags, allOutputFlagsBack);
+}
+
+static MicrophoneInfo generateValidMicrophoneInfo() {
+ MicrophoneInfo micInfo{};
+ micInfo.deviceAddress.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC);
+ micInfo.channelMapping.resize(1);
+ micInfo.channelMapping[0] = AudioMicrophoneChannelMapping::DIRECT;
+ micInfo.location = AudioMicrophoneLocation::MAINBODY_MOVABLE;
+ micInfo.group = 42;
+ micInfo.indexInTheGroup = 13;
+ micInfo.sensitivity = 65.5;
+ micInfo.maxSpl = 100.5;
+ micInfo.minSpl = 36.6;
+ micInfo.directionality = AudioMicrophoneDirectionality::HYPER_CARDIOID;
+ micInfo.frequencyResponse.resize(1);
+ micInfo.frequencyResponse[0].frequency = 1000;
+ micInfo.frequencyResponse[0].level = 85;
+ micInfo.position.x = 0;
+ micInfo.position.y = 1;
+ micInfo.position.z = 0;
+ micInfo.orientation.x = 0;
+ micInfo.orientation.y = 0;
+ micInfo.orientation.z = 1;
+ return micInfo;
+}
+
+TEST(CoreUtils, ConvertInvalidMicrophoneInfo) {
+ MicrophoneInfo invalid;
+ audio_microphone_characteristic_t halInvalid{};
+ halInvalid.device = kInvalidHalDevice;
+ EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoFromHal(halInvalid, &invalid));
+
+ MicrophoneInfo oversizeDeviceId = generateValidMicrophoneInfo();
+ oversizeDeviceId.deviceId = std::string(AUDIO_MICROPHONE_ID_MAX_LEN + 1, 'A');
+ EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(oversizeDeviceId, &halInvalid));
+ MicrophoneInfo invalidDeviceType = generateValidMicrophoneInfo();
+ invalidDeviceType.deviceAddress.deviceType = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(invalidDeviceType, &halInvalid));
+ MicrophoneInfo oversizeChannelMapping = generateValidMicrophoneInfo();
+ oversizeChannelMapping.channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX + 1);
+ EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(oversizeChannelMapping, &halInvalid));
+ MicrophoneInfo oversizeFrequencyResponses = generateValidMicrophoneInfo();
+ oversizeFrequencyResponses.frequencyResponse.resize(AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES +
+ 1);
+ EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(oversizeFrequencyResponses, &halInvalid));
+}
+
+TEST(CoreUtils, ConvertMicrophoneInfo) {
+ MicrophoneInfo micInfo = generateValidMicrophoneInfo();
+ audio_microphone_characteristic_t halMicInfo;
+ EXPECT_EQ(NO_ERROR, CoreUtils::microphoneInfoToHal(micInfo, &halMicInfo));
+ MicrophoneInfo micInfoBack;
+ EXPECT_EQ(NO_ERROR, CoreUtils::microphoneInfoFromHal(halMicInfo, &micInfoBack));
+ EXPECT_EQ(micInfo, micInfoBack);
+}
+
+static RecordTrackMetadata generateMinimalRecordTrackMetadata() {
+ RecordTrackMetadata metadata{};
+ metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT);
+ metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return metadata;
+}
+
+static RecordTrackMetadata generateValidRecordTrackMetadata() {
+ RecordTrackMetadata metadata = generateMinimalRecordTrackMetadata();
+ metadata.tags.resize(1);
+ metadata.tags[0] = "VX_GOOGLE_42";
+ metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
+ metadata.gain = 1.0;
+ return metadata;
+}
+
+static RecordTrackMetadata generateValidRecordTrackMetadataWithDevice() {
+ RecordTrackMetadata metadata = generateValidRecordTrackMetadata();
+ metadata.destination.device({});
+ metadata.destination.device().deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER);
+ return metadata;
+}
+
+using SinkTracks = hidl_vec<RecordTrackMetadata>;
+
+TEST(CoreUtils, ConvertInvalidSinkMetadata) {
+ SinkMetadata invalidSource;
+ invalidSource.tracks = SinkTracks{generateMinimalRecordTrackMetadata()};
+ invalidSource.tracks[0].source = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHal(invalidSource, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidSource,
+ false /*ignoreNonVendorTags*/, nullptr));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataToHalV7(invalidSource, true /*ignoreNonVendorTags*/, nullptr));
+ SinkMetadata invalidDeviceType;
+ invalidDeviceType.tracks = SinkTracks{generateValidRecordTrackMetadataWithDevice()};
+ invalidDeviceType.tracks[0].destination.device().deviceType = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHal(invalidDeviceType, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidDeviceType,
+ false /*ignoreNonVendorTags*/, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidDeviceType,
+ true /*ignoreNonVendorTags*/, nullptr));
+ SinkMetadata invalidChannelMask;
+ invalidChannelMask.tracks = SinkTracks{generateValidRecordTrackMetadata()};
+ invalidChannelMask.tracks[0].channelMask = "random string";
+ // Channel mask is sliced away by 'sinkMetadataToHal'
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(invalidChannelMask, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidChannelMask,
+ false /*ignoreNonVendorTags*/, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidChannelMask,
+ true /*ignoreNonVendorTags*/, nullptr));
+ SinkMetadata invalidTags;
+ invalidTags.tracks = SinkTracks{generateValidRecordTrackMetadata()};
+ invalidTags.tracks[0].tags[0] = "random string";
+ // Tags are sliced away by 'sinkMetadataToHal'
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(invalidTags, nullptr));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataToHalV7(invalidTags, false /*ignoreNonVendorTags*/, nullptr));
+ // Non-vendor tags should be filtered out.
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataToHalV7(invalidTags, true /*ignoreNonVendorTags*/, nullptr));
+
+ // Verify that a default-initialized metadata is valid.
+ std::vector<record_track_metadata_t> halValid(1, record_track_metadata_t{});
+ std::vector<record_track_metadata_v7_t> halValidV7(1, record_track_metadata_v7_t{});
+ SinkMetadata valid;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHal(halValid, &valid));
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataFromHalV7(halValidV7, false /*ignoreNonVendorTags*/, &valid));
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataFromHalV7(halValidV7, true /*ignoreNonVendorTags*/, &valid));
+
+ std::vector<record_track_metadata_t> halInvalidSource = {{.source = kInvalidHalSource}};
+ std::vector<record_track_metadata_v7_t> halInvalidSourceV7 = {
+ {.base = {.source = kInvalidHalSource}}};
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHal(halInvalidSource, &invalidSource));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataFromHalV7(halInvalidSourceV7, false /*ignoreNonVendorTags*/,
+ &invalidSource));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHalV7(
+ halInvalidSourceV7, true /*ignoreNonVendorTags*/, &invalidSource));
+ std::vector<record_track_metadata_t> halInvalidDeviceType = {
+ {.dest_device = kInvalidHalDevice}};
+ std::vector<record_track_metadata_v7_t> halInvalidDeviceTypeV7 = {
+ {.base = {.dest_device = kInvalidHalDevice}}};
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHal(halInvalidDeviceType, &invalidDeviceType));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataFromHalV7(halInvalidDeviceTypeV7,
+ false /*ignoreNonVendorTags*/, &invalidDeviceType));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataFromHalV7(halInvalidDeviceTypeV7, true /*ignoreNonVendorTags*/,
+ &invalidDeviceType));
+ std::vector<record_track_metadata_v7_t> halInvalidChannelMaskV7 = {
+ {.channel_mask = kInvalidHalChannelMask}};
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataFromHalV7(halInvalidChannelMaskV7,
+ false /*ignoreNonVendorTags*/, &invalidChannelMask));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sinkMetadataFromHalV7(halInvalidChannelMaskV7,
+ true /*ignoreNonVendorTags*/, &invalidChannelMask));
+ std::vector<record_track_metadata_v7_t> halInvalidTagsV7 = {{.tags = "random string"}};
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHalV7(
+ halInvalidTagsV7, false /*ignoreNonVendorTags*/, &invalidTags));
+ // Non-vendor tags should be filtered out.
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHalV7(
+ halInvalidTagsV7, true /*ignoreNonVendorTags*/, &invalidTags));
+}
+
+TEST(CoreUtils, ConvertEmptySinkMetadata) {
+ SinkMetadata emptySinkMetadata;
+ std::vector<record_track_metadata_t> halEmptySinkMetadata;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(emptySinkMetadata, &halEmptySinkMetadata));
+ EXPECT_TRUE(halEmptySinkMetadata.empty());
+ SinkMetadata emptySinkMetadataBack;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataFromHal(halEmptySinkMetadata, &emptySinkMetadataBack));
+ EXPECT_EQ(emptySinkMetadata, emptySinkMetadataBack);
+ std::vector<record_track_metadata_v7_t> halEmptySinkMetadataV7;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataToHalV7(emptySinkMetadata, false /*ignoreNonVendorTags*/,
+ &halEmptySinkMetadataV7));
+ EXPECT_TRUE(halEmptySinkMetadataV7.empty());
+ SinkMetadata emptySinkMetadataBackFromV7;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHalV7(halEmptySinkMetadataV7,
+ false /*ignoreNonVendorTags*/,
+ &emptySinkMetadataBackFromV7));
+ EXPECT_EQ(emptySinkMetadata, emptySinkMetadataBackFromV7);
+}
+
+class SinkMetadataConvertTest : public ::testing::TestWithParam<SinkTracks> {};
+
+TEST_P(SinkMetadataConvertTest, ToFromHal) {
+ SinkMetadata sinkMetadata;
+ sinkMetadata.tracks = GetParam();
+ std::vector<record_track_metadata_t> halSinkMetadata;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(sinkMetadata, &halSinkMetadata));
+ EXPECT_EQ(sinkMetadata.tracks.size(), halSinkMetadata.size());
+ SinkMetadata sinkMetadataBackTrimmed;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHal(halSinkMetadata, &sinkMetadataBackTrimmed));
+ // Can't compare 'sinkMetadata' to 'sinkMetadataBackTrimmed'
+ std::vector<record_track_metadata_v7_t> halSinkMetadataV7;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHalV7(sinkMetadata, false /*ignoreNonVendorTags*/,
+ &halSinkMetadataV7));
+ EXPECT_EQ(sinkMetadata.tracks.size(), halSinkMetadataV7.size());
+ SinkMetadata sinkMetadataBackFromV7;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataFromHalV7(halSinkMetadataV7, false /*ignoreNonVendorTags*/,
+ &sinkMetadataBackFromV7));
+ EXPECT_EQ(sinkMetadata, sinkMetadataBackFromV7);
+ std::vector<record_track_metadata_v7_t> halSinkMetadataV7FromTrimmed;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sinkMetadataToHalV7(sinkMetadataBackTrimmed, false /*ignoreNonVendorTags*/,
+ &halSinkMetadataV7FromTrimmed));
+ EXPECT_EQ(sinkMetadata.tracks.size(), halSinkMetadataV7FromTrimmed.size());
+ SinkMetadata sinkMetadataBackFromV7Trimmed;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHalV7(halSinkMetadataV7FromTrimmed,
+ false /*ignoreNonVendorTags*/,
+ &sinkMetadataBackFromV7Trimmed));
+ EXPECT_EQ(sinkMetadataBackTrimmed, sinkMetadataBackFromV7Trimmed);
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidRecordTrackMetadatas, SinkMetadataConvertTest,
+ ::testing::Values(SinkTracks{generateMinimalRecordTrackMetadata()},
+ SinkTracks{generateValidRecordTrackMetadata()},
+ SinkTracks{generateValidRecordTrackMetadataWithDevice()},
+ SinkTracks{
+ generateMinimalRecordTrackMetadata(),
+ generateValidRecordTrackMetadata(),
+ generateValidRecordTrackMetadataWithDevice()}));
+
+static PlaybackTrackMetadata generateMinimalPlaybackTrackMetadata() {
+ PlaybackTrackMetadata metadata{};
+ metadata.usage = toString(xsd::AudioUsage::AUDIO_USAGE_UNKNOWN);
+ metadata.contentType = toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN);
+ metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+ return metadata;
+}
+
+static PlaybackTrackMetadata generateValidPlaybackTrackMetadata() {
+ PlaybackTrackMetadata metadata = generateMinimalPlaybackTrackMetadata();
+ metadata.tags.resize(1);
+ metadata.tags[0] = "VX_GOOGLE_42";
+ metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
+ metadata.gain = 1.0;
+ return metadata;
+}
+
+using SourceTracks = hidl_vec<PlaybackTrackMetadata>;
+
+TEST(CoreUtils, ConvertInvalidSourceMetadata) {
+ SourceMetadata invalidUsage;
+ invalidUsage.tracks = SourceTracks{generateMinimalPlaybackTrackMetadata()};
+ invalidUsage.tracks[0].usage = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHal(invalidUsage, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidUsage,
+ false /*ignoreNonVendorTags*/, nullptr));
+ SourceMetadata invalidContentType;
+ invalidContentType.tracks = SourceTracks{generateMinimalPlaybackTrackMetadata()};
+ invalidContentType.tracks[0].contentType = "random string";
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHal(invalidContentType, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidContentType,
+ false /*ignoreNonVendorTags*/, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidContentType,
+ true /*ignoreNonVendorTags*/, nullptr));
+ SourceMetadata invalidChannelMask;
+ invalidChannelMask.tracks = SourceTracks{generateValidPlaybackTrackMetadata()};
+ invalidChannelMask.tracks[0].channelMask = "random string";
+ // Channel mask is sliced away by 'sourceMetadataToHal'
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHal(invalidChannelMask, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidChannelMask,
+ false /*ignoreNonVendorTags*/, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidChannelMask,
+ true /*ignoreNonVendorTags*/, nullptr));
+ SourceMetadata invalidTags;
+ invalidTags.tracks = SourceTracks{generateValidPlaybackTrackMetadata()};
+ invalidTags.tracks[0].tags[0] = "random string";
+ // Tags are sliced away by 'sourceMetadataToHal'
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHal(invalidTags, nullptr));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidTags,
+ false /*ignoreNonVendorTags*/, nullptr));
+ // Non-vendor tags should be filtered out.
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataToHalV7(invalidTags, true /*ignoreNonVendorTags*/, nullptr));
+
+ // Verify that a default-initialized metadata is valid.
+ std::vector<playback_track_metadata_t> halValid(1, playback_track_metadata_t{});
+ std::vector<playback_track_metadata_v7_t> halValidV7(1, playback_track_metadata_v7_t{});
+ SourceMetadata valid;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHal(halValid, &valid));
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(halValidV7,
+ false /*ignoreNonVendorTags*/, &valid));
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataFromHalV7(halValidV7, true /*ignoreNonVendorTags*/, &valid));
+
+ std::vector<playback_track_metadata_t> halInvalidUsage = {{.usage = kInvalidHalUsage}};
+ std::vector<playback_track_metadata_v7_t> halInvalidUsageV7 = {
+ {.base = {.usage = kInvalidHalUsage}}};
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHal(halInvalidUsage, &invalidUsage));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHalV7(
+ halInvalidUsageV7, false /*ignoreNonVendorTags*/, &invalidUsage));
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHalV7(
+ halInvalidUsageV7, true /*ignoreNonVendorTags*/, &invalidUsage));
+ std::vector<playback_track_metadata_t> halInvalidContentType = {
+ {.content_type = kInvalidHalContentType}};
+ std::vector<playback_track_metadata_v7_t> halInvalidContentTypeV7 = {
+ {.base = {.content_type = kInvalidHalContentType}}};
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sourceMetadataFromHal(halInvalidContentType, &invalidContentType));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sourceMetadataFromHalV7(
+ halInvalidContentTypeV7, false /*ignoreNonVendorTags*/, &invalidContentType));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sourceMetadataFromHalV7(
+ halInvalidContentTypeV7, true /*ignoreNonVendorTags*/, &invalidContentType));
+ std::vector<playback_track_metadata_v7_t> halInvalidChannelMaskV7 = {
+ {.channel_mask = kInvalidHalChannelMask}};
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sourceMetadataFromHalV7(
+ halInvalidChannelMaskV7, false /*ignoreNonVendorTags*/, &invalidChannelMask));
+ EXPECT_EQ(BAD_VALUE,
+ CoreUtils::sourceMetadataFromHalV7(
+ halInvalidChannelMaskV7, true /*ignoreNonVendorTags*/, &invalidChannelMask));
+ std::vector<playback_track_metadata_v7_t> halInvalidTagsV7 = {{.tags = "random string"}};
+ EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHalV7(
+ halInvalidTagsV7, false /*ignoreNonVendorTags*/, &invalidTags));
+ // Non-vendor tags should be filtered out.
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(
+ halInvalidTagsV7, true /*ignoreNonVendorTags*/, &invalidTags));
+}
+
+TEST(CoreUtils, ConvertEmptySourceMetadata) {
+ SourceMetadata emptySourceMetadata;
+ std::vector<playback_track_metadata_t> halEmptySourceMetadata;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataToHal(emptySourceMetadata, &halEmptySourceMetadata));
+ EXPECT_TRUE(halEmptySourceMetadata.empty());
+ SourceMetadata emptySourceMetadataBack;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataFromHal(halEmptySourceMetadata, &emptySourceMetadataBack));
+ EXPECT_EQ(emptySourceMetadata, emptySourceMetadataBack);
+ std::vector<playback_track_metadata_v7_t> halEmptySourceMetadataV7;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataToHalV7(emptySourceMetadata, false /*ignoreNonVendorTags*/,
+ &halEmptySourceMetadataV7));
+ EXPECT_TRUE(halEmptySourceMetadataV7.empty());
+ SourceMetadata emptySourceMetadataBackFromV7;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(halEmptySourceMetadataV7,
+ false /*ignoreNonVendorTags*/,
+ &emptySourceMetadataBackFromV7));
+ EXPECT_EQ(emptySourceMetadata, emptySourceMetadataBackFromV7);
+}
+
+class SourceMetadataConvertTest : public ::testing::TestWithParam<SourceTracks> {};
+
+TEST_P(SourceMetadataConvertTest, ToFromHal) {
+ SourceMetadata sourceMetadata;
+ sourceMetadata.tracks = GetParam();
+ std::vector<playback_track_metadata_t> halSourceMetadata;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHal(sourceMetadata, &halSourceMetadata));
+ EXPECT_EQ(sourceMetadata.tracks.size(), halSourceMetadata.size());
+ SourceMetadata sourceMetadataBackTrimmed;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataFromHal(halSourceMetadata, &sourceMetadataBackTrimmed));
+ // Can't compare 'sourceMetadata' to 'sourceMetadataBackTrimmed'
+ std::vector<playback_track_metadata_v7_t> halSourceMetadataV7;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataToHalV7(sourceMetadata, false /*ignoreNonVendorTags*/,
+ &halSourceMetadataV7));
+ EXPECT_EQ(sourceMetadata.tracks.size(), halSourceMetadataV7.size());
+ SourceMetadata sourceMetadataBackFromV7;
+ EXPECT_EQ(NO_ERROR,
+ CoreUtils::sourceMetadataFromHalV7(halSourceMetadataV7, false /*ignoreNonVendorTags*/,
+ &sourceMetadataBackFromV7));
+ EXPECT_EQ(sourceMetadata, sourceMetadataBackFromV7);
+ std::vector<playback_track_metadata_v7_t> halSourceMetadataV7FromTrimmed;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHalV7(sourceMetadataBackTrimmed,
+ false /*ignoreNonVendorTags*/,
+ &halSourceMetadataV7FromTrimmed));
+ EXPECT_EQ(sourceMetadata.tracks.size(), halSourceMetadataV7FromTrimmed.size());
+ SourceMetadata sourceMetadataBackFromV7Trimmed;
+ EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(halSourceMetadataV7FromTrimmed,
+ false /*ignoreNonVendorTags*/,
+ &sourceMetadataBackFromV7Trimmed));
+ EXPECT_EQ(sourceMetadataBackTrimmed, sourceMetadataBackFromV7Trimmed);
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidPlaybackTrackMetadatas, SourceMetadataConvertTest,
+ ::testing::Values(SourceTracks{generateMinimalPlaybackTrackMetadata()},
+ SourceTracks{generateValidPlaybackTrackMetadata()},
+ SourceTracks{generateMinimalPlaybackTrackMetadata(),
+ generateValidPlaybackTrackMetadata()}));
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 5076dcf..bb7c6d3 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -336,24 +336,24 @@
ASSERT_RESULT(okOrNotSupported, stream->updateSourceMetadata(
{{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
- {},
+ 0.1, // gain
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
- 0.1},
+ {}}, // tags
{toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH),
- {}, // tags
+ 1.0,
toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
- 1.0},
+ {}},
{toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION),
- {}, // tags
+ 0.0,
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::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
- 0.3}}}
+ {}}}}
));
// clang-format on
// Set no metadata as if all stream track had stopped
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index a0cd612..99b1120 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -8,7 +8,6 @@
"AudioBufferManager.cpp",
"AutomaticGainControlEffect.cpp",
"BassBoostEffect.cpp",
- "Conversions.cpp",
"DownmixEffect.cpp",
"Effect.cpp",
"EffectsFactory.cpp",
@@ -51,6 +50,7 @@
"android.hardware.audio.common@2.0",
"android.hardware.audio.common@2.0-util",
"android.hardware.audio.effect@2.0",
+ "android.hardware.audio.effect@2.0-util",
],
cflags: [
"-DMAJOR_VERSION=2",
@@ -66,6 +66,7 @@
"android.hardware.audio.common@4.0",
"android.hardware.audio.common@4.0-util",
"android.hardware.audio.effect@4.0",
+ "android.hardware.audio.effect@4.0-util",
],
cflags: [
"-DMAJOR_VERSION=4",
@@ -81,6 +82,7 @@
"android.hardware.audio.common@5.0",
"android.hardware.audio.common@5.0-util",
"android.hardware.audio.effect@5.0",
+ "android.hardware.audio.effect@5.0-util",
],
cflags: [
"-DMAJOR_VERSION=5",
@@ -96,6 +98,7 @@
"android.hardware.audio.common@6.0",
"android.hardware.audio.common@6.0-util",
"android.hardware.audio.effect@6.0",
+ "android.hardware.audio.effect@6.0-util",
],
cflags: [
"-DMAJOR_VERSION=6",
@@ -111,6 +114,7 @@
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-util",
"android.hardware.audio.effect@7.0",
+ "android.hardware.audio.effect@7.0-util",
],
cflags: [
"-DMAJOR_VERSION=7",
diff --git a/audio/effect/all-versions/default/Conversions.cpp b/audio/effect/all-versions/default/Conversions.cpp
deleted file mode 100644
index 0cc8767..0000000
--- a/audio/effect/all-versions/default/Conversions.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Conversions.h"
-#include "UuidUtils.h"
-
-#include <memory.h>
-#include <stdio.h>
-
-#include <common/all-versions/VersionUtils.h>
-
-using ::android::hardware::audio::common::utils::EnumBitfield;
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
-
-void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
- EffectDescriptor* descriptor) {
- UuidUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
- UuidUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
- descriptor->flags = EnumBitfield<EffectFlags>(halDescriptor.flags);
- descriptor->cpuLoad = halDescriptor.cpuLoad;
- descriptor->memoryUsage = halDescriptor.memoryUsage;
- memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
- memcpy(descriptor->implementor.data(), halDescriptor.implementor,
- descriptor->implementor.size());
-}
-
-std::string uuidToString(const effect_uuid_t& halUuid) {
- char str[64];
- snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", halUuid.timeLow,
- halUuid.timeMid, halUuid.timeHiAndVersion, halUuid.clockSeq, halUuid.node[0],
- halUuid.node[1], halUuid.node[2], halUuid.node[3], halUuid.node[4], halUuid.node[5]);
- return str;
-}
-
-} // namespace implementation
-} // namespace CPP_VERSION
-} // namespace effect
-} // namespace audio
-} // namespace hardware
-} // namespace android
diff --git a/audio/effect/all-versions/default/Conversions.h b/audio/effect/all-versions/default/Conversions.h
deleted file mode 100644
index 75aab24..0000000
--- a/audio/effect/all-versions/default/Conversions.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_CONVERSIONS_H_
-#define ANDROID_HARDWARE_AUDIO_EFFECT_CONVERSIONS_H_
-
-#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
-
-#include <string>
-
-#include <system/audio_effect.h>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-
-void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
- EffectDescriptor* descriptor);
-std::string uuidToString(const effect_uuid_t& halUuid);
-
-} // namespace implementation
-} // namespace CPP_VERSION
-} // namespace effect
-} // namespace audio
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_AUDIO_EFFECT_CONVERSIONS_H_
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 58f1779..ccfc6b2 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -19,7 +19,6 @@
#define LOG_TAG "EffectHAL"
#define ATRACE_TAG ATRACE_TAG_AUDIO
-#include "Conversions.h"
#include "Effect.h"
#include "common/all-versions/default/EffectMap.h"
@@ -30,6 +29,7 @@
#include <HidlUtils.h>
#include <android/log.h>
#include <media/EffectsFactoryApi.h>
+#include <util/EffectUtils.h>
#include <utils/Trace.h>
#include "VersionUtils.h"
@@ -202,34 +202,6 @@
halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
}
-void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig,
- EffectBufferConfig* config) {
- config->buffer.id = 0;
- config->buffer.frameCount = 0;
- config->samplingRateHz = halConfig.samplingRate;
- config->channels = AudioChannelBitfield(halConfig.channels);
- config->format = AudioFormat(halConfig.format);
- config->accessMode = EffectBufferAccess(halConfig.accessMode);
- config->mask = static_cast<decltype(config->mask)>(halConfig.mask);
-}
-
-// static
-void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
- // Note: setting the buffers directly is considered obsolete. They need to be set
- // using 'setProcessBuffers'.
- halConfig->buffer.frameCount = 0;
- halConfig->buffer.raw = NULL;
- halConfig->samplingRate = config.samplingRateHz;
- halConfig->channels = static_cast<uint32_t>(config.channels);
- // Note: The framework code does not use BP.
- halConfig->bufferProvider.cookie = NULL;
- halConfig->bufferProvider.getBuffer = NULL;
- halConfig->bufferProvider.releaseBuffer = NULL;
- halConfig->format = static_cast<uint8_t>(config.format);
- halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
- halConfig->mask = static_cast<uint8_t>(config.mask);
-}
-
#else // MAJOR_VERSION <= 6
void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
@@ -247,68 +219,8 @@
(void)HidlUtils::audioChannelMaskToHal(config.auxChannels, &halConfig->aux_channels);
}
-void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig,
- EffectBufferConfig* config) {
- config->buffer.unspecified();
- audio_config_base_t halConfigBase = {halConfig.samplingRate,
- static_cast<audio_channel_mask_t>(halConfig.channels),
- static_cast<audio_format_t>(halConfig.format)};
- (void)HidlUtils::audioConfigBaseOptionalFromHal(
- halConfigBase, mIsInput, halConfig.mask & EFFECT_CONFIG_FORMAT,
- halConfig.mask & EFFECT_CONFIG_SMP_RATE, halConfig.mask & EFFECT_CONFIG_CHANNELS,
- &config->base);
- if (halConfig.mask & EFFECT_CONFIG_ACC_MODE) {
- config->accessMode.value(EffectBufferAccess(halConfig.accessMode));
- }
-}
-
-// static
-void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
- // Note: setting the buffers directly is considered obsolete. They need to be set
- // using 'setProcessBuffers'.
- halConfig->buffer.frameCount = 0;
- halConfig->buffer.raw = nullptr;
- audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
- bool formatSpecified = false, sRateSpecified = false, channelMaskSpecified = false;
- (void)HidlUtils::audioConfigBaseOptionalToHal(config.base, &halConfigBase, &formatSpecified,
- &sRateSpecified, &channelMaskSpecified);
- halConfig->mask = 0;
- if (sRateSpecified) {
- halConfig->mask |= EFFECT_CONFIG_SMP_RATE;
- halConfig->samplingRate = halConfigBase.sample_rate;
- }
- if (channelMaskSpecified) {
- halConfig->mask |= EFFECT_CONFIG_CHANNELS;
- halConfig->channels = halConfigBase.channel_mask;
- }
- if (formatSpecified) {
- halConfig->mask |= EFFECT_CONFIG_FORMAT;
- halConfig->format = halConfigBase.format;
- }
- // Note: The framework code does not use BP.
- halConfig->bufferProvider.cookie = nullptr;
- halConfig->bufferProvider.getBuffer = nullptr;
- halConfig->bufferProvider.releaseBuffer = nullptr;
- if (config.accessMode.getDiscriminator() ==
- EffectBufferConfig::OptionalAccessMode::hidl_discriminator::value) {
- halConfig->mask |= EFFECT_CONFIG_ACC_MODE;
- halConfig->accessMode = static_cast<uint8_t>(config.accessMode.value());
- }
-}
-
#endif // MAJOR_VERSION <= 6
-void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
- effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
- effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
-}
-
-// static
-void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
- effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
- effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
-}
-
// static
void Effect::effectOffloadParamToHal(const EffectOffloadParameter& offload,
effect_offload_param_t* halOffload) {
@@ -373,7 +285,7 @@
(*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
EffectConfig config;
if (status == OK) {
- effectConfigFromHal(halConfig, &config);
+ status = EffectUtils::effectConfigFromHal(halConfig, mIsInput, &config);
}
cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
}
@@ -538,7 +450,7 @@
const sp<IEffectBufferProviderCallback>& inputBufferProvider,
const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
effect_config_t halConfig;
- effectConfigToHal(config, &halConfig);
+ EffectUtils::effectConfigToHal(config, &halConfig);
if (inputBufferProvider != 0) {
LOG_FATAL("Using input buffer provider is not supported");
}
@@ -733,7 +645,7 @@
status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
EffectDescriptor descriptor;
if (status == OK) {
- effectDescriptorFromHal(halDescriptor, &descriptor);
+ status = EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
}
_hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
return Void();
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 9aa47ea..d5218f7 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -203,11 +203,6 @@
EffectAuxChannelsConfig* config);
static void effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
channel_config_t* halConfig);
- void effectBufferConfigFromHal(const buffer_config_t& halConfig, EffectBufferConfig* config);
- static void effectBufferConfigToHal(const EffectBufferConfig& config,
- buffer_config_t* halConfig);
- void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
- static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
static void effectOffloadParamToHal(const EffectOffloadParameter& offload,
effect_offload_param_t* halOffload);
static std::vector<uint8_t> parameterToHal(uint32_t paramSize, const void* paramData,
diff --git a/audio/effect/all-versions/default/EffectsFactory.cpp b/audio/effect/all-versions/default/EffectsFactory.cpp
index 1ea990b..eb1cb49 100644
--- a/audio/effect/all-versions/default/EffectsFactory.cpp
+++ b/audio/effect/all-versions/default/EffectsFactory.cpp
@@ -19,7 +19,6 @@
#include "AcousticEchoCancelerEffect.h"
#include "AutomaticGainControlEffect.h"
#include "BassBoostEffect.h"
-#include "Conversions.h"
#include "DownmixEffect.h"
#include "Effect.h"
#include "EnvironmentalReverbEffect.h"
@@ -27,11 +26,11 @@
#include "LoudnessEnhancerEffect.h"
#include "NoiseSuppressionEffect.h"
#include "PresetReverbEffect.h"
-#include "UuidUtils.h"
#include "VirtualizerEffect.h"
#include "VisualizerEffect.h"
#include "common/all-versions/default/EffectMap.h"
+#include <UuidUtils.h>
#include <android/log.h>
#include <media/EffectsFactoryApi.h>
#include <system/audio_effects/effect_aec.h>
@@ -45,6 +44,7 @@
#include <system/audio_effects/effect_presetreverb.h>
#include <system/audio_effects/effect_virtualizer.h>
#include <system/audio_effects/effect_visualizer.h>
+#include <util/EffectUtils.h>
namespace android {
namespace hardware {
@@ -107,7 +107,7 @@
effect_descriptor_t halDescriptor;
status = EffectQueryEffect(i, &halDescriptor);
if (status == OK) {
- effectDescriptorFromHal(halDescriptor, &result[i]);
+ EffectUtils::effectDescriptorFromHal(halDescriptor, &result[i]);
} else {
ALOGE("Error querying effect at position %d / %d: %s", i, numEffects,
strerror(-status));
@@ -141,11 +141,11 @@
effect_descriptor_t halDescriptor;
status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
EffectDescriptor descriptor;
- effectDescriptorFromHal(halDescriptor, &descriptor);
+ EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
Result retval(Result::OK);
if (status != OK) {
- ALOGE("Error querying effect descriptor for %s: %s", uuidToString(halUuid).c_str(),
- strerror(-status));
+ ALOGE("Error querying effect descriptor for %s: %s",
+ UuidUtils::uuidToString(halUuid).c_str(), strerror(-status));
if (status == -ENOENT) {
retval = Result::INVALID_ARGUMENTS;
} else {
@@ -191,13 +191,14 @@
effect = dispatchEffectInstanceCreation(halDescriptor, handle);
effectId = EffectMap::getInstance().add(handle);
} else {
- ALOGE("Error querying effect descriptor for %s: %s", uuidToString(halUuid).c_str(),
- strerror(-status));
+ ALOGE("Error querying effect descriptor for %s: %s",
+ UuidUtils::uuidToString(halUuid).c_str(), strerror(-status));
EffectRelease(handle);
}
}
if (status != OK) {
- ALOGE("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
+ ALOGE("Error creating effect %s: %s", UuidUtils::uuidToString(halUuid).c_str(),
+ strerror(-status));
if (status == -ENOENT) {
retval = Result::INVALID_ARGUMENTS;
} else {
diff --git a/audio/effect/all-versions/default/TEST_MAPPING b/audio/effect/all-versions/default/TEST_MAPPING
new file mode 100644
index 0000000..b66e4e4
--- /dev/null
+++ b/audio/effect/all-versions/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "android.hardware.audio.effect@7.0-util_tests"
+ }
+ ]
+}
diff --git a/audio/effect/all-versions/default/util/Android.bp b/audio/effect/all-versions/default/util/Android.bp
new file mode 100644
index 0000000..5ba19d3
--- /dev/null
+++ b/audio/effect/all-versions/default/util/Android.bp
@@ -0,0 +1,136 @@
+cc_defaults {
+ name: "android.hardware.audio.effect-util_default",
+ defaults: ["hidl_defaults"],
+
+ vendor_available: true,
+
+ export_include_dirs: ["include"],
+
+ srcs: [
+ "EffectUtils.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libhidlbase",
+ "android.hardware.audio.common-util",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.audio.common-util",
+ ],
+
+ header_libs: [
+ "libaudio_system_headers",
+ "libhardware_headers",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio.effect@2.0-util",
+ defaults: ["android.hardware.audio.effect-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@2.0",
+ "android.hardware.audio.common@2.0-util",
+ "android.hardware.audio.effect@2.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=2",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio.effect@4.0-util",
+ defaults: ["android.hardware.audio.effect-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@4.0",
+ "android.hardware.audio.common@4.0-util",
+ "android.hardware.audio.effect@4.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=4",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio.effect@5.0-util",
+ defaults: ["android.hardware.audio.effect-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@5.0",
+ "android.hardware.audio.common@5.0-util",
+ "android.hardware.audio.effect@5.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=5",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.audio.effect@6.0-util",
+ defaults: ["android.hardware.audio.effect-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@6.0",
+ "android.hardware.audio.common@6.0-util",
+ "android.hardware.audio.effect@6.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=6",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+cc_library {
+ name: "android.hardware.audio.effect@7.0-util",
+ defaults: ["android.hardware.audio.effect-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio.effect@7.0",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of conversion utilities.
+cc_test {
+ name: "android.hardware.audio.effect@7.0-util_tests",
+ defaults: ["android.hardware.audio.effect-util_default"],
+
+ srcs: ["tests/effectutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.
+ static_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.0-enums",
+ "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio.effect@7.0",
+ "android.hardware.audio.effect@7.0-util",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/effect/all-versions/default/util/EffectUtils.cpp b/audio/effect/all-versions/default/util/EffectUtils.cpp
new file mode 100644
index 0000000..1c0419a
--- /dev/null
+++ b/audio/effect/all-versions/default/util/EffectUtils.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory.h>
+
+#include <HidlUtils.h>
+#include <UuidUtils.h>
+#include <common/all-versions/VersionUtils.h>
+
+#include "util/EffectUtils.h"
+
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::common::utils::EnumBitfield;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace CPP_VERSION {
+namespace implementation {
+
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+
+#define CONVERT_CHECKED(expr, result) \
+ if (status_t status = (expr); status != NO_ERROR) { \
+ result = status; \
+ }
+
+#if MAJOR_VERSION <= 6
+
+status_t EffectUtils::effectBufferConfigFromHal(const buffer_config_t& halConfig, bool /*isInput*/,
+ EffectBufferConfig* config) {
+ config->buffer.id = 0;
+ config->buffer.frameCount = 0;
+ config->samplingRateHz = halConfig.samplingRate;
+ config->channels = EnumBitfield<AudioChannelMask>(halConfig.channels);
+ config->format = AudioFormat(halConfig.format);
+ config->accessMode = EffectBufferAccess(halConfig.accessMode);
+ config->mask = EnumBitfield<EffectConfigParameters>(halConfig.mask);
+ return NO_ERROR;
+}
+
+status_t EffectUtils::effectBufferConfigToHal(const EffectBufferConfig& config,
+ buffer_config_t* halConfig) {
+ // Note: setting the buffers directly is considered obsolete. They need to be set
+ // using 'setProcessBuffers'.
+ halConfig->buffer.frameCount = 0;
+ halConfig->buffer.raw = nullptr;
+ halConfig->samplingRate = config.samplingRateHz;
+ halConfig->channels = static_cast<uint32_t>(config.channels);
+ // Note: The framework code does not use BP.
+ halConfig->bufferProvider.cookie = nullptr;
+ halConfig->bufferProvider.getBuffer = nullptr;
+ halConfig->bufferProvider.releaseBuffer = nullptr;
+ halConfig->format = static_cast<uint8_t>(config.format);
+ halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
+ halConfig->mask = static_cast<uint8_t>(config.mask);
+ return NO_ERROR;
+}
+
+#else
+
+status_t EffectUtils::effectBufferConfigFromHal(const buffer_config_t& halConfig, bool isInput,
+ EffectBufferConfig* config) {
+ status_t result = NO_ERROR;
+ config->buffer.unspecified();
+ audio_config_base_t halConfigBase = {halConfig.samplingRate,
+ static_cast<audio_channel_mask_t>(halConfig.channels),
+ static_cast<audio_format_t>(halConfig.format)};
+ CONVERT_CHECKED(HidlUtils::audioConfigBaseOptionalFromHal(
+ halConfigBase, isInput, halConfig.mask & EFFECT_CONFIG_FORMAT,
+ halConfig.mask & EFFECT_CONFIG_SMP_RATE,
+ halConfig.mask & EFFECT_CONFIG_CHANNELS, &config->base),
+ result);
+ if (halConfig.mask & EFFECT_CONFIG_ACC_MODE) {
+ config->accessMode.value(EffectBufferAccess(halConfig.accessMode));
+ }
+ return result;
+}
+
+status_t EffectUtils::effectBufferConfigToHal(const EffectBufferConfig& config,
+ buffer_config_t* halConfig) {
+ status_t result = NO_ERROR;
+ // Note: setting the buffers directly is considered obsolete. They need to be set
+ // using 'setProcessBuffers'.
+ halConfig->buffer.frameCount = 0;
+ halConfig->buffer.raw = nullptr;
+ audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
+ bool formatSpecified = false, sRateSpecified = false, channelMaskSpecified = false;
+ CONVERT_CHECKED(
+ HidlUtils::audioConfigBaseOptionalToHal(config.base, &halConfigBase, &formatSpecified,
+ &sRateSpecified, &channelMaskSpecified),
+ result);
+ halConfig->mask = 0;
+ if (sRateSpecified) {
+ halConfig->mask |= EFFECT_CONFIG_SMP_RATE;
+ halConfig->samplingRate = halConfigBase.sample_rate;
+ }
+ if (channelMaskSpecified) {
+ halConfig->mask |= EFFECT_CONFIG_CHANNELS;
+ halConfig->channels = halConfigBase.channel_mask;
+ }
+ if (formatSpecified) {
+ halConfig->mask |= EFFECT_CONFIG_FORMAT;
+ halConfig->format = halConfigBase.format;
+ }
+ // Note: The framework code does not use BP.
+ halConfig->bufferProvider.cookie = nullptr;
+ halConfig->bufferProvider.getBuffer = nullptr;
+ halConfig->bufferProvider.releaseBuffer = nullptr;
+ if (config.accessMode.getDiscriminator() ==
+ EffectBufferConfig::OptionalAccessMode::hidl_discriminator::value) {
+ halConfig->mask |= EFFECT_CONFIG_ACC_MODE;
+ halConfig->accessMode = static_cast<uint8_t>(config.accessMode.value());
+ }
+ return result;
+}
+
+#endif // MAJOR_VERSION >= 6
+
+status_t EffectUtils::effectConfigFromHal(const effect_config_t& halConfig, bool isInput,
+ EffectConfig* config) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(effectBufferConfigFromHal(halConfig.inputCfg, isInput, &config->inputCfg),
+ result);
+ CONVERT_CHECKED(effectBufferConfigFromHal(halConfig.outputCfg, isInput, &config->outputCfg),
+ result);
+ return result;
+}
+
+status_t EffectUtils::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
+ status_t result = NO_ERROR;
+ CONVERT_CHECKED(effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg), result);
+ CONVERT_CHECKED(effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg), result);
+ return result;
+}
+
+status_t EffectUtils::effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
+ EffectDescriptor* descriptor) {
+ UuidUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
+ UuidUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
+ descriptor->flags = EnumBitfield<EffectFlags>(halDescriptor.flags);
+ descriptor->cpuLoad = halDescriptor.cpuLoad;
+ descriptor->memoryUsage = halDescriptor.memoryUsage;
+ memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
+ memcpy(descriptor->implementor.data(), halDescriptor.implementor,
+ descriptor->implementor.size());
+ return NO_ERROR;
+}
+
+status_t EffectUtils::effectDescriptorToHal(const EffectDescriptor& descriptor,
+ effect_descriptor_t* halDescriptor) {
+ UuidUtils::uuidToHal(descriptor.type, &halDescriptor->type);
+ UuidUtils::uuidToHal(descriptor.uuid, &halDescriptor->uuid);
+ halDescriptor->flags = static_cast<uint32_t>(descriptor.flags);
+ halDescriptor->cpuLoad = descriptor.cpuLoad;
+ halDescriptor->memoryUsage = descriptor.memoryUsage;
+ memcpy(halDescriptor->name, descriptor.name.data(), descriptor.name.size());
+ memcpy(halDescriptor->implementor, descriptor.implementor.data(),
+ descriptor.implementor.size());
+ return NO_ERROR;
+}
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace effect
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/effect/all-versions/default/util/include/util/EffectUtils.h b/audio/effect/all-versions/default/util/include/util/EffectUtils.h
new file mode 100644
index 0000000..23963b4
--- /dev/null
+++ b/audio/effect/all-versions/default/util/include/util/EffectUtils.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// clang-format off
+#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
+// clang-format on
+
+#include <system/audio_effect.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace CPP_VERSION {
+namespace implementation {
+
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
+struct EffectUtils {
+ static status_t effectBufferConfigFromHal(const buffer_config_t& halConfig, bool isInput,
+ EffectBufferConfig* config);
+ static status_t effectBufferConfigToHal(const EffectBufferConfig& config,
+ buffer_config_t* halConfig);
+ static status_t effectConfigFromHal(const effect_config_t& halConfig, bool isInput,
+ EffectConfig* config);
+ static status_t effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
+ static status_t effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
+ EffectDescriptor* descriptor);
+ static status_t effectDescriptorToHal(const EffectDescriptor& descriptor,
+ effect_descriptor_t* halDescriptor);
+};
+
+} // namespace implementation
+} // namespace CPP_VERSION
+} // namespace effect
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
new file mode 100644
index 0000000..7eb8cd2
--- /dev/null
+++ b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "EffectUtils_Test"
+#include <log/log.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <system/audio_effect.h>
+#include <util/EffectUtils.h>
+#include <xsdc/XsdcSupport.h>
+
+using namespace android;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
+static constexpr audio_format_t kInvalidHalFormat = AUDIO_FORMAT_INVALID;
+
+// Not generated automatically because AudioBuffer contains
+// instances of hidl_memory which can't be compared properly
+// in general case due to presence of handles.
+//
+// However, in this particular case, handles must not present
+// thus comparison is possible.
+//
+// operator== must be defined in the same namespace as the structures.
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace CPP_VERSION {
+inline bool operator==(const AudioBuffer& lhs, const AudioBuffer& rhs) {
+ return lhs.id == rhs.id && lhs.frameCount == rhs.frameCount && lhs.data.handle() == nullptr &&
+ rhs.data.handle() == nullptr;
+}
+
+inline bool operator==(const EffectBufferConfig& lhs, const EffectBufferConfig& rhs) {
+ return lhs.buffer.getDiscriminator() == rhs.buffer.getDiscriminator() &&
+ (lhs.buffer.getDiscriminator() ==
+ EffectBufferConfig::OptionalBuffer::hidl_discriminator::unspecified ||
+ lhs.buffer.buf() == rhs.buffer.buf()) &&
+ lhs.base == rhs.base && lhs.accessMode == rhs.accessMode;
+}
+
+inline bool operator==(const EffectConfig& lhs, const EffectConfig& rhs) {
+ return lhs.inputCfg == rhs.inputCfg && lhs.outputCfg == rhs.outputCfg;
+}
+} // namespace CPP_VERSION
+} // namespace effect
+} // namespace audio
+} // namespace hardware
+} // namespace android
+
+TEST(EffectUtils, ConvertInvalidBufferConfig) {
+ buffer_config_t halInvalid;
+ EffectBufferConfig invalidChannelMask;
+ invalidChannelMask.base.channelMask.value("random string");
+ EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigToHal(invalidChannelMask, &halInvalid));
+ EffectBufferConfig invalidFormat;
+ invalidFormat.base.format.value("random string");
+ EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigToHal(invalidFormat, &halInvalid));
+
+ buffer_config_t halInvalidChannelMask;
+ EffectBufferConfig invalid;
+ halInvalidChannelMask.channels = kInvalidHalChannelMask;
+ halInvalidChannelMask.mask = EFFECT_CONFIG_CHANNELS;
+ EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigFromHal(halInvalidChannelMask,
+ false /*isInput*/, &invalid));
+ EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigFromHal(halInvalidChannelMask,
+ true /*isInput*/, &invalid));
+ buffer_config_t halInvalidFormat;
+ halInvalidFormat.format = (uint8_t)kInvalidHalFormat;
+ halInvalidFormat.mask = EFFECT_CONFIG_FORMAT;
+ EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigFromHal(halInvalidFormat, false /*isInput*/,
+ &invalid));
+ EXPECT_EQ(BAD_VALUE,
+ EffectUtils::effectBufferConfigFromHal(halInvalidFormat, true /*isInput*/, &invalid));
+}
+
+TEST(EffectUtils, ConvertBufferConfig) {
+ EffectBufferConfig empty;
+ buffer_config_t halEmpty;
+ EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigToHal(empty, &halEmpty));
+ EffectBufferConfig emptyBackOut;
+ EXPECT_EQ(NO_ERROR,
+ EffectUtils::effectBufferConfigFromHal(halEmpty, false /*isInput*/, &emptyBackOut));
+ EXPECT_EQ(empty, emptyBackOut);
+ EffectBufferConfig emptyBackIn;
+ EXPECT_EQ(NO_ERROR,
+ EffectUtils::effectBufferConfigFromHal(halEmpty, true /*isInput*/, &emptyBackIn));
+ EXPECT_EQ(empty, emptyBackIn);
+
+ EffectBufferConfig chanMask;
+ chanMask.base.channelMask.value(toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO));
+ buffer_config_t halChanMask;
+ EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigToHal(chanMask, &halChanMask));
+ EffectBufferConfig chanMaskBack;
+ EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigFromHal(halChanMask, false /*isInput*/,
+ &chanMaskBack));
+ EXPECT_EQ(chanMask, chanMaskBack);
+
+ EffectBufferConfig format;
+ format.base.format.value(toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT));
+ buffer_config_t halFormat;
+ EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigToHal(format, &halFormat));
+ EffectBufferConfig formatBackOut;
+ EXPECT_EQ(NO_ERROR,
+ EffectUtils::effectBufferConfigFromHal(halFormat, false /*isInput*/, &formatBackOut));
+ EXPECT_EQ(format, formatBackOut);
+ EffectBufferConfig formatBackIn;
+ EXPECT_EQ(NO_ERROR,
+ EffectUtils::effectBufferConfigFromHal(halFormat, true /*isInput*/, &formatBackIn));
+ EXPECT_EQ(format, formatBackIn);
+}
+
+TEST(EffectUtils, ConvertDescriptor) {
+ EffectDescriptor desc{};
+ effect_descriptor_t halDesc;
+ EXPECT_EQ(NO_ERROR, EffectUtils::effectDescriptorToHal(desc, &halDesc));
+ EffectDescriptor descBack;
+ EXPECT_EQ(NO_ERROR, EffectUtils::effectDescriptorFromHal(halDesc, &descBack));
+ EXPECT_EQ(desc, descBack);
+}