| /* |
| * 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 PATH(APM_XSD_ENUMS_H_FILENAME) |
| #include <system/audio.h> |
| #include <util/CoreUtils.h> |
| #include <xsdc/XsdcSupport.h> |
| |
| using namespace android; |
| using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION; |
| using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION; |
| using ::android::hardware::hidl_vec; |
| using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils; |
| namespace xsd { |
| using namespace ::android::audio::policy::configuration::CPP_VERSION; |
| } |
| |
| 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()})); |