/* * Copyright (C) 2020 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 #include #include #define LOG_TAG "HidlUtils_Test" #include #include #include PATH(APM_XSD_ENUMS_H_FILENAME) #include #include using namespace android; using ::android::hardware::hidl_vec; using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION; using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils; 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(0xFFFFFFFFU); static constexpr audio_devices_t kInvalidHalDevice = static_cast(0xFFFFFFFFU); static constexpr audio_format_t kInvalidHalFormat = AUDIO_FORMAT_INVALID; static constexpr audio_gain_mode_t kInvalidHalGainMode = static_cast(0xFFFFFFFFU); // AUDIO_SOURCE_INVALID is framework-only. static constexpr audio_source_t kInvalidHalSource = static_cast(-1); // AUDIO_STREAM_DEFAULT is framework-only static constexpr audio_stream_type_t kInvalidHalStreamType = static_cast(-2); static constexpr audio_usage_t kInvalidHalUsage = static_cast(0xFFFFFFFFU); static constexpr audio_encapsulation_type_t kInvalidEncapsulationType = static_cast(0xFFFFFFFFU); static constexpr audio_standard_t kInvalidAudioStandard = static_cast(0xFFFFFFFFU); TEST(HidlUtils, ConvertInvalidChannelMask) { AudioChannelMask invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskFromHal(kInvalidHalChannelMask, false /*isInput*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskFromHal(kInvalidHalChannelMask, true /*isInput*/, &invalid)); audio_channel_mask_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskToHal("", &halInvalid)); // INVALID channel mask is not in XSD thus it's not allowed for transfer over HIDL. EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskToHal("AUDIO_CHANNEL_INVALID", &halInvalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMaskToHal("random string", &halInvalid)); } // Might move these to the audio_policy_configuration_V7_0-enums library // if there would be usages in the default wrapper code. In that case, // it would be better to reimplement these methods using a proper switch statement // over all known enum values. static bool isInputChannelMask(xsd::AudioChannelMask channelMask) { return toString(channelMask).find("_CHANNEL_IN_") != std::string::npos; } static bool isOutputChannelMask(xsd::AudioChannelMask channelMask) { return toString(channelMask).find("_CHANNEL_OUT_") != std::string::npos; } static bool isIndexChannelMask(xsd::AudioChannelMask channelMask) { return toString(channelMask).find("_CHANNEL_INDEX_") != std::string::npos; } TEST(HidlUtils, ConvertChannelMask) { for (const auto enumVal : xsdc_enum_range{}) { const AudioChannelMask channelMask = toString(enumVal); audio_channel_mask_t halChannelMask, halChannelMaskBack; AudioChannelMask channelMaskBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskToHal(channelMask, &halChannelMask)) << "Conversion of \"" << channelMask << "\" failed"; EXPECT_EQ(enumVal != xsd::AudioChannelMask::AUDIO_CHANNEL_NONE, audio_channel_mask_is_valid(halChannelMask)) << "Validity of \"" << channelMask << "\" is not as expected"; if (bool isInput = isInputChannelMask(enumVal); isInput || isOutputChannelMask(enumVal)) { EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskFromHal(halChannelMask, isInput, &channelMaskBack)) << "Conversion of " << (isInput ? "input" : "output") << " channel mask " << halChannelMask << " failed"; // Due to aliased values, the result of 'fromHal' might not be the same // as 'channelMask', thus we need to compare the results of 'toHal' conversion instead. EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskToHal(channelMaskBack, &halChannelMaskBack)) << "Conversion of \"" << channelMaskBack << "\" failed"; EXPECT_EQ(halChannelMask, halChannelMaskBack); } else if (isIndexChannelMask(enumVal) || enumVal == xsd::AudioChannelMask::AUDIO_CHANNEL_NONE) { // Conversions for indexed masks and "none" must not depend on the provided direction. EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskFromHal(halChannelMask, true /*isInput*/, &channelMaskBack)) << "Conversion of indexed / none channel mask " << halChannelMask << " failed (as input channel mask)"; EXPECT_EQ(channelMask, channelMaskBack); EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMaskFromHal( halChannelMask, false /*isInput*/, &channelMaskBack)) << "Conversion of indexed / none channel mask " << halChannelMask << " failed (as output channel mask)"; EXPECT_EQ(channelMask, channelMaskBack); } else { FAIL() << "Unrecognized channel mask \"" << channelMask << "\""; } } } TEST(HidlUtils, ConvertInvalidChannelMasksFromHal) { std::vector validAndInvalidChannelMasks = { toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO), "random string", ""}; hidl_vec validChannelMask; EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMasksFromHal(validAndInvalidChannelMasks, &validChannelMask)); EXPECT_EQ(1, validChannelMask.size()); EXPECT_EQ(validAndInvalidChannelMasks[0], validChannelMask[0]); std::vector invalidChannelMasks = {"random string", ""}; hidl_vec empty; EXPECT_EQ(BAD_VALUE, HidlUtils::audioChannelMasksFromHal(invalidChannelMasks, &empty)); EXPECT_EQ(0, empty.size()); } TEST(HidlUtils, ConvertChannelMasksFromHal) { std::vector allHalChannelMasks; for (const auto enumVal : xsdc_enum_range{}) { allHalChannelMasks.push_back(toString(enumVal)); } hidl_vec allChannelMasks; EXPECT_EQ(NO_ERROR, HidlUtils::audioChannelMasksFromHal(allHalChannelMasks, &allChannelMasks)); EXPECT_EQ(allHalChannelMasks.size(), allChannelMasks.size()); for (size_t i = 0; i < allHalChannelMasks.size(); ++i) { EXPECT_EQ(allHalChannelMasks[i], allChannelMasks[i]); } } static AudioConfigBase generateValidConfigBase(bool isInput) { AudioConfigBase configBase; configBase.sampleRateHz = 44100; configBase.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); configBase.channelMask = isInput ? toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_STEREO) : toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); return configBase; } TEST(HidlUtils, ConvertInvalidConfigBase) { AudioConfigBase invalid; audio_config_base_t halInvalidChannelMask = AUDIO_CONFIG_BASE_INITIALIZER; halInvalidChannelMask.channel_mask = kInvalidHalChannelMask; EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseFromHal(halInvalidChannelMask, false /*isInput*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseFromHal(halInvalidChannelMask, true /*isInput*/, &invalid)); audio_config_base_t halInvalidFormat = AUDIO_CONFIG_BASE_INITIALIZER; halInvalidFormat.format = kInvalidHalFormat; EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseFromHal(halInvalidFormat, false /*isInput*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseFromHal(halInvalidFormat, true /*isInput*/, &invalid)); audio_config_base_t halInvalid; AudioConfigBase invalidChannelMask = generateValidConfigBase(false /*isInput*/); invalidChannelMask.channelMask = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseToHal(invalidChannelMask, &halInvalid)); AudioConfigBase invalidFormat = generateValidConfigBase(false /*isInput*/); invalidFormat.format = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseToHal(invalidFormat, &halInvalid)); } TEST(HidlUtils, ConvertConfigBaseDefault) { audio_config_base_t halBaseDefault = AUDIO_CONFIG_BASE_INITIALIZER; AudioConfigBase baseDefaultOut, baseDefaultIn; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseFromHal(halBaseDefault, false /*isInput*/, &baseDefaultOut)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseFromHal(halBaseDefault, true /*isInput*/, &baseDefaultIn)); EXPECT_EQ(baseDefaultOut, baseDefaultIn); audio_config_base_t halBaseDefaultBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseToHal(baseDefaultOut, &halBaseDefaultBack)); EXPECT_EQ(halBaseDefault.sample_rate, halBaseDefaultBack.sample_rate); EXPECT_EQ(halBaseDefault.channel_mask, halBaseDefaultBack.channel_mask); EXPECT_EQ(halBaseDefault.format, halBaseDefaultBack.format); } TEST(HidlUtils, ConvertConfigBase) { AudioConfigBase configBaseOut = generateValidConfigBase(false /*isInput*/); audio_config_base_t halConfigBaseOut; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseToHal(configBaseOut, &halConfigBaseOut)); AudioConfigBase configBaseOutBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseFromHal(halConfigBaseOut, false /*isInput*/, &configBaseOutBack)); EXPECT_EQ(configBaseOut, configBaseOutBack); AudioConfigBase configBaseIn = generateValidConfigBase(true /*isInput*/); audio_config_base_t halConfigBaseIn; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseToHal(configBaseIn, &halConfigBaseIn)); AudioConfigBase configBaseInBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseFromHal(halConfigBaseIn, true /*isInput*/, &configBaseInBack)); EXPECT_EQ(configBaseIn, configBaseInBack); } TEST(HidlUtils, ConvertInvalidConfigBaseOptional) { AudioConfigBaseOptional invalid; audio_config_base_t halInvalidChannelMask = AUDIO_CONFIG_BASE_INITIALIZER; halInvalidChannelMask.channel_mask = kInvalidHalChannelMask; EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidChannelMask, false /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, true /*channelMaskSpecified*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidChannelMask, true /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, true /*channelMaskSpecified*/, &invalid)); // Unspecified invalid values are ignored AudioConfigBaseOptional unspecified; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidChannelMask, false /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &unspecified)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidChannelMask, true /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &unspecified)); audio_config_base_t halInvalidFormat = AUDIO_CONFIG_BASE_INITIALIZER; halInvalidFormat.format = kInvalidHalFormat; EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidFormat, false /*isInput*/, true /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidFormat, true /*isInput*/, true /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &invalid)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidFormat, false /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &unspecified)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halInvalidFormat, true /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &unspecified)); audio_config_base_t halInvalid; AudioConfigBaseOptional invalidChannelMask; bool formatSpecified, sampleRateSpecified, channelMaskSpecified; invalidChannelMask.channelMask.value("random string"); EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseOptionalToHal( invalidChannelMask, &halInvalid, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); AudioConfigBaseOptional invalidFormat; invalidFormat.format.value("random string"); EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigBaseOptionalToHal(invalidFormat, &halInvalid, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); } TEST(HidlUtils, ConvertConfigBaseOptionalDefault) { audio_config_base_t halBaseDefault = AUDIO_CONFIG_BASE_INITIALIZER; AudioConfigBaseOptional baseDefaultUnspecOut, baseDefaultUnspecIn; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halBaseDefault, false /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &baseDefaultUnspecOut)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halBaseDefault, true /*isInput*/, false /*formatSpecified*/, false /*sampleRateSpecified*/, false /*channelMaskSpecified*/, &baseDefaultUnspecIn)); EXPECT_EQ(baseDefaultUnspecOut, baseDefaultUnspecIn); audio_config_base_t halBaseDefaultUnspecBack = AUDIO_CONFIG_BASE_INITIALIZER; bool formatSpecified, sampleRateSpecified, channelMaskSpecified; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalToHal( baseDefaultUnspecOut, &halBaseDefaultUnspecBack, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); EXPECT_FALSE(formatSpecified); EXPECT_FALSE(sampleRateSpecified); EXPECT_FALSE(channelMaskSpecified); EXPECT_EQ(halBaseDefault.sample_rate, halBaseDefaultUnspecBack.sample_rate); EXPECT_EQ(halBaseDefault.channel_mask, halBaseDefaultUnspecBack.channel_mask); EXPECT_EQ(halBaseDefault.format, halBaseDefaultUnspecBack.format); AudioConfigBaseOptional baseDefaultSpecOut, baseDefaultSpecIn; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halBaseDefault, false /*isInput*/, true /*formatSpecified*/, true /*sampleRateSpecified*/, true /*channelMaskSpecified*/, &baseDefaultSpecOut)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halBaseDefault, true /*isInput*/, true /*formatSpecified*/, true /*sampleRateSpecified*/, true /*channelMaskSpecified*/, &baseDefaultSpecIn)); EXPECT_EQ(baseDefaultSpecOut, baseDefaultSpecIn); audio_config_base_t halBaseDefaultSpecBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalToHal( baseDefaultSpecOut, &halBaseDefaultSpecBack, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); EXPECT_TRUE(formatSpecified); EXPECT_TRUE(sampleRateSpecified); EXPECT_TRUE(channelMaskSpecified); EXPECT_EQ(halBaseDefault.sample_rate, halBaseDefaultSpecBack.sample_rate); EXPECT_EQ(halBaseDefault.channel_mask, halBaseDefaultSpecBack.channel_mask); EXPECT_EQ(halBaseDefault.format, halBaseDefaultSpecBack.format); } TEST(HidlUtils, ConvertConfigBaseOptionalEmpty) { AudioConfigBaseOptional empty; bool formatSpecified, sampleRateSpecified, channelMaskSpecified; audio_config_base_t halEmpty = AUDIO_CONFIG_BASE_INITIALIZER; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalToHal(empty, &halEmpty, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); EXPECT_FALSE(formatSpecified); EXPECT_FALSE(sampleRateSpecified); EXPECT_FALSE(channelMaskSpecified); AudioConfigBaseOptional emptyOutBack, emptyInBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halEmpty, false /*isInput*/, formatSpecified, sampleRateSpecified, channelMaskSpecified, &emptyOutBack)); EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halEmpty, true /*isInput*/, formatSpecified, sampleRateSpecified, channelMaskSpecified, &emptyInBack)); EXPECT_EQ(emptyOutBack, emptyInBack); EXPECT_EQ(empty, emptyOutBack); } TEST(HidlUtils, ConvertConfigBaseOptional) { AudioConfigBase validBaseOut = generateValidConfigBase(false /*isInput*/); AudioConfigBaseOptional configBaseOut; configBaseOut.format.value(validBaseOut.format); configBaseOut.sampleRateHz.value(validBaseOut.sampleRateHz); configBaseOut.channelMask.value(validBaseOut.channelMask); audio_config_base_t halConfigBaseOut; bool formatSpecified, sampleRateSpecified, channelMaskSpecified; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalToHal( configBaseOut, &halConfigBaseOut, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); EXPECT_TRUE(formatSpecified); EXPECT_TRUE(sampleRateSpecified); EXPECT_TRUE(channelMaskSpecified); AudioConfigBaseOptional configBaseOutBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halConfigBaseOut, false /*isInput*/, formatSpecified, sampleRateSpecified, channelMaskSpecified, &configBaseOutBack)); EXPECT_EQ(configBaseOut, configBaseOutBack); AudioConfigBase validBaseIn = generateValidConfigBase(true /*isInput*/); AudioConfigBaseOptional configBaseIn; configBaseIn.format.value(validBaseIn.format); configBaseIn.sampleRateHz.value(validBaseIn.sampleRateHz); configBaseIn.channelMask.value(validBaseIn.channelMask); audio_config_base_t halConfigBaseIn; formatSpecified = false; sampleRateSpecified = false; channelMaskSpecified = false; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalToHal( configBaseIn, &halConfigBaseIn, &formatSpecified, &sampleRateSpecified, &channelMaskSpecified)); EXPECT_TRUE(formatSpecified); EXPECT_TRUE(sampleRateSpecified); EXPECT_TRUE(channelMaskSpecified); AudioConfigBaseOptional configBaseInBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigBaseOptionalFromHal( halConfigBaseIn, true /*isInput*/, formatSpecified, sampleRateSpecified, channelMaskSpecified, &configBaseInBack)); EXPECT_EQ(configBaseIn, configBaseInBack); } TEST(HidlUtils, ConvertInvalidContentType) { AudioContentType invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioContentTypeFromHal(kInvalidHalContentType, &invalid)); audio_content_type_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioContentTypeToHal("", &halInvalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioContentTypeToHal("random string", &halInvalid)); } TEST(HidlUtils, ConvertContentType) { for (const auto enumVal : xsdc_enum_range{}) { const AudioContentType contentType = toString(enumVal); audio_content_type_t halContentType; AudioContentType contentTypeBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioContentTypeToHal(contentType, &halContentType)) << "Conversion of \"" << contentType << "\" failed"; EXPECT_EQ(NO_ERROR, HidlUtils::audioContentTypeFromHal(halContentType, &contentTypeBack)) << "Conversion of content type " << halContentType << " failed"; EXPECT_EQ(contentType, contentTypeBack); } } TEST(HidlUtils, ConvertInvalidDeviceType) { AudioDevice invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioDeviceTypeFromHal(kInvalidHalDevice, &invalid)); audio_devices_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioDeviceTypeToHal("", &halInvalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioDeviceTypeToHal("random string", &halInvalid)); } TEST(HidlUtils, ConvertDeviceType) { for (const auto enumVal : xsdc_enum_range{}) { const AudioDevice deviceType = toString(enumVal); audio_devices_t halDeviceType, halDeviceTypeBack; AudioDevice deviceTypeBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioDeviceTypeToHal(deviceType, &halDeviceType)) << "Conversion of \"" << deviceType << "\" failed"; if (enumVal != xsd::AudioDevice::AUDIO_DEVICE_NONE) { EXPECT_TRUE(audio_is_input_device(halDeviceType) || audio_is_output_device(halDeviceType)) << "Device \"" << deviceType << "\" is neither input, nor output device"; } else { EXPECT_FALSE(audio_is_input_device(halDeviceType)); EXPECT_FALSE(audio_is_output_device(halDeviceType)); } EXPECT_EQ(NO_ERROR, HidlUtils::audioDeviceTypeFromHal(halDeviceType, &deviceTypeBack)) << "Conversion of device type " << halDeviceType << " failed"; // Due to aliased values, the result of 'fromHal' might not be the same // as 'deviceType', thus we need to compare the results of 'toHal' conversion instead. EXPECT_EQ(NO_ERROR, HidlUtils::audioDeviceTypeToHal(deviceTypeBack, &halDeviceTypeBack)) << "Conversion of \"" << deviceTypeBack << "\" failed"; EXPECT_EQ(halDeviceType, halDeviceTypeBack); } } // The enums module is too small to have unit tests on its own. TEST(HidlUtils, VendorExtension) { EXPECT_TRUE(xsd::isVendorExtension("VX_GOOGLE_VR_42")); EXPECT_TRUE(xsd::isVendorExtension("VX_QCM_SPK")); EXPECT_FALSE(xsd::isVendorExtension("")); EXPECT_FALSE(xsd::isVendorExtension("random string")); EXPECT_FALSE(xsd::isVendorExtension("VX_")); EXPECT_FALSE(xsd::isVendorExtension("VX_X")); EXPECT_FALSE(xsd::isVendorExtension("VX_X_")); EXPECT_FALSE(xsd::isVendorExtension("VX_X_X")); EXPECT_FALSE(xsd::isVendorExtension("VX_XX_X")); EXPECT_FALSE(xsd::isVendorExtension("VX_GOOGLE_$$")); EXPECT_FALSE(xsd::isVendorExtension("VX_$CM_SPK")); } TEST(HidlUtils, ConvertInvalidDeviceAddress) { DeviceAddress invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, nullptr, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, "", &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_IP, nullptr, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_IP, "", &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_USB_HEADSET, nullptr, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressFromHal(AUDIO_DEVICE_OUT_USB_HEADSET, "", &invalid)); audio_devices_t halInvalid; char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {}; invalid = {}; invalid.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressToHal(invalid, &halInvalid, halAddress)); invalid.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_IP); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressToHal(invalid, &halInvalid, halAddress)); invalid.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET); EXPECT_EQ(BAD_VALUE, HidlUtils::deviceAddressToHal(invalid, &halInvalid, halAddress)); } static void ConvertDeviceAddress(const DeviceAddress& device) { audio_devices_t halDeviceType; char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {}; EXPECT_EQ(NO_ERROR, HidlUtils::deviceAddressToHal(device, &halDeviceType, halDeviceAddress)); DeviceAddress deviceBack; EXPECT_EQ(NO_ERROR, HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, &deviceBack)); EXPECT_EQ(device, deviceBack); } TEST(HidlUtils, ConvertUniqueDeviceAddress) { DeviceAddress speaker; speaker.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER); ConvertDeviceAddress(speaker); DeviceAddress micWithAddress; micWithAddress.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC); micWithAddress.address.id("bottom"); ConvertDeviceAddress(micWithAddress); } TEST(HidlUtils, ConvertA2dpDeviceAddress) { DeviceAddress a2dpSpeaker; a2dpSpeaker.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER); a2dpSpeaker.address.mac(std::array{1, 2, 3, 4, 5, 6}); ConvertDeviceAddress(a2dpSpeaker); } TEST(HidlUtils, ConvertIpv4DeviceAddress) { DeviceAddress ipv4; ipv4.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_IP); ipv4.address.ipv4(std::array{1, 2, 3, 4}); ConvertDeviceAddress(ipv4); } TEST(HidlUtils, ConvertUsbDeviceAddress) { DeviceAddress usbHeadset; usbHeadset.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET); usbHeadset.address.alsa({1, 2}); ConvertDeviceAddress(usbHeadset); } TEST(HidlUtils, ConvertBusDeviceAddress) { DeviceAddress bus; bus.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_BUS); bus.address.id("bus_device"); ConvertDeviceAddress(bus); } TEST(HidlUtils, ConvertRSubmixDeviceAddress) { DeviceAddress rSubmix; rSubmix.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX); rSubmix.address.id(AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); ConvertDeviceAddress(rSubmix); } TEST(HidlUtils, ConvertVendorDeviceAddress) { // The address part is not mandatory, both cases must work. { DeviceAddress vendor; vendor.deviceType = "VX_GOOGLE_VR"; audio_devices_t halDeviceType; char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {}; // Ignore the result. Vendors will also add the extended device into // the list of devices in audio-hal-enums.h. Without that, the conversion // officially fails, but it still maps the device type to NONE. (void)HidlUtils::deviceAddressToHal(vendor, &halDeviceType, halDeviceAddress); EXPECT_EQ(AUDIO_DEVICE_NONE, halDeviceType); EXPECT_EQ(0, strnlen(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN)); } { DeviceAddress vendor; vendor.deviceType = "VX_GOOGLE_VR"; vendor.address.id("vr1"); audio_devices_t halDeviceType; char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN] = {}; // Ignore the result. Vendors will also add the extended device into // the list of devices in audio-hal-enums.h. Without that, the conversion // officially fails, but it still maps the device type to NONE and converts // the address. (void)HidlUtils::deviceAddressToHal(vendor, &halDeviceType, halDeviceAddress); EXPECT_EQ(AUDIO_DEVICE_NONE, halDeviceType); EXPECT_EQ(0, strncmp("vr1", halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN)); } } TEST(HidlUtils, ConvertInvalidFormat) { AudioFormat invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatFromHal(kInvalidHalFormat, &invalid)); audio_format_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatToHal("", &halInvalid)); // INVALID format is not in XSD thus it's not allowed for transfer over HIDL. EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatToHal("AUDIO_FORMAT_INVALID", &halInvalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatToHal("random string", &halInvalid)); } TEST(HidlUtils, ConvertFormat) { for (const auto enumVal : xsdc_enum_range{}) { const AudioFormat format = toString(enumVal); audio_format_t halFormat; AudioFormat formatBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioFormatToHal(format, &halFormat)) << "Conversion of \"" << format << "\" failed"; EXPECT_EQ(enumVal != xsd::AudioFormat::AUDIO_FORMAT_DEFAULT, audio_is_valid_format(halFormat)) << "Validity of \"" << format << "\" is not as expected"; EXPECT_EQ(NO_ERROR, HidlUtils::audioFormatFromHal(halFormat, &formatBack)) << "Conversion of format " << halFormat << " failed"; EXPECT_EQ(format, formatBack); } } TEST(HidlUtils, ConvertInvalidFormatsFromHal) { std::vector validAndInvalidFormats = { toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT), "random string", ""}; hidl_vec validFormat; EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatsFromHal(validAndInvalidFormats, &validFormat)); EXPECT_EQ(1, validFormat.size()); EXPECT_EQ(validAndInvalidFormats[0], validFormat[0]); std::vector invalidFormats = {"random string", ""}; hidl_vec empty; EXPECT_EQ(BAD_VALUE, HidlUtils::audioFormatsFromHal(invalidFormats, &empty)); EXPECT_EQ(0, empty.size()); } TEST(HidlUtils, ConvertFormatsFromHal) { std::vector allHalFormats; for (const auto enumVal : xsdc_enum_range{}) { allHalFormats.push_back(toString(enumVal)); } hidl_vec allFormats; EXPECT_EQ(NO_ERROR, HidlUtils::audioFormatsFromHal(allHalFormats, &allFormats)); EXPECT_EQ(allHalFormats.size(), allFormats.size()); for (size_t i = 0; i < allHalFormats.size(); ++i) { EXPECT_EQ(allHalFormats[i], allFormats[i]); } } TEST(HidlUtils, ConvertInvalidGainModeMask) { hidl_vec invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainModeMaskFromHal(kInvalidHalGainMode, &invalid)); audio_gain_mode_t halInvalid; invalid.resize(1); invalid[0] = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainModeMaskToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertGainModeMask) { hidl_vec emptyGainModes; audio_gain_mode_t halEmptyGainModes; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskToHal(emptyGainModes, &halEmptyGainModes)); hidl_vec emptyGainModesBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskFromHal(halEmptyGainModes, &emptyGainModesBack)); EXPECT_EQ(emptyGainModes, emptyGainModesBack); std::vector allEnumValues; for (const auto enumVal : xsdc_enum_range{}) { allEnumValues.push_back(toString(enumVal)); } hidl_vec allGainModes; allGainModes.resize(allEnumValues.size()); for (size_t i = 0; i < allEnumValues.size(); ++i) { allGainModes[i] = allEnumValues[i]; } audio_gain_mode_t halAllGainModes; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskToHal(allGainModes, &halAllGainModes)); hidl_vec allGainModesBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainModeMaskFromHal(halAllGainModes, &allGainModesBack)); EXPECT_EQ(allGainModes, allGainModesBack); } TEST(HidlUtils, ConvertInvalidSource) { AudioSource invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioSourceFromHal(kInvalidHalSource, &invalid)); audio_source_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioSourceToHal("", &halInvalid)); // INVALID source is not in XSD thus it's not allowed for transfer over HIDL. EXPECT_EQ(BAD_VALUE, HidlUtils::audioSourceToHal("AUDIO_SOURCE_INVALID", &halInvalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioSourceToHal("random string", &halInvalid)); } TEST(HidlUtils, ConvertSource) { for (const auto enumVal : xsdc_enum_range{}) { const AudioSource source = toString(enumVal); audio_source_t halSource; AudioSource sourceBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioSourceToHal(source, &halSource)) << "Conversion of \"" << source << "\" failed"; EXPECT_EQ(enumVal != xsd::AudioSource::AUDIO_SOURCE_DEFAULT, audio_is_valid_audio_source(halSource)) << "Validity of \"" << source << "\" is not as expected"; EXPECT_EQ(NO_ERROR, HidlUtils::audioSourceFromHal(halSource, &sourceBack)) << "Conversion of source " << halSource << " failed"; EXPECT_EQ(source, sourceBack); } } TEST(HidlUtils, ConvertInvalidStreamType) { AudioStreamType invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioStreamTypeFromHal(kInvalidHalStreamType, &invalid)); audio_stream_type_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioStreamTypeToHal("random string", &halInvalid)); } TEST(HidlUtils, ConvertDefaultStreamType) { AudioStreamType streamDefault = ""; audio_stream_type_t halStreamDefault; EXPECT_EQ(NO_ERROR, HidlUtils::audioStreamTypeToHal(streamDefault, &halStreamDefault)); AudioStreamType streamDefaultBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioStreamTypeFromHal(halStreamDefault, &streamDefaultBack)); EXPECT_EQ(streamDefault, streamDefaultBack); } TEST(HidlUtils, ConvertStreamType) { for (const auto enumVal : xsdc_enum_range{}) { const AudioStreamType streamType = toString(enumVal); audio_stream_type_t halStreamType; AudioStreamType streamTypeBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioStreamTypeToHal(streamType, &halStreamType)) << "Conversion of \"" << streamType << "\" failed"; EXPECT_EQ(NO_ERROR, HidlUtils::audioStreamTypeFromHal(halStreamType, &streamTypeBack)) << "Conversion of stream type " << halStreamType << " failed"; EXPECT_EQ(streamType, streamTypeBack); } } TEST(HidlUtils, ConvertInvalidGain) { AudioGain invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainFromHal({.mode = kInvalidHalGainMode}, false /*isInput*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainFromHal({.mode = kInvalidHalGainMode}, true /*isInput*/, &invalid)); struct audio_gain halInvalid; invalid.mode.resize(1); invalid.mode[0] = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertGain) { AudioGain gain = {}; gain.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); struct audio_gain halGain; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainToHal(gain, &halGain)); AudioGain gainBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainFromHal(halGain, false /*isInput*/, &gainBack)); EXPECT_EQ(gain, gainBack); struct audio_gain halGainBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainToHal(gainBack, &halGainBack)); EXPECT_TRUE(audio_gains_are_equal(&halGain, &halGainBack)); } TEST(HidlUtils, ConvertInvalidGainConfig) { AudioGainConfig invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainConfigFromHal({.mode = kInvalidHalGainMode}, false /*isInput*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainConfigFromHal({.mode = kInvalidHalGainMode}, true /*isInput*/, &invalid)); struct audio_gain_config halInvalid; invalid.mode.resize(1); invalid.mode[0] = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioGainConfigToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertGainConfig) { AudioGainConfig gainConfig = {}; gainConfig.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); struct audio_gain_config halGainConfig; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainConfigToHal(gainConfig, &halGainConfig)); AudioGainConfig gainConfigBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainConfigFromHal(halGainConfig, false /*isInput*/, &gainConfigBack)); EXPECT_EQ(gainConfig, gainConfigBack); struct audio_gain_config halGainConfigBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioGainConfigToHal(gainConfigBack, &halGainConfigBack)); EXPECT_TRUE(audio_gain_config_are_equal(&halGainConfig, &halGainConfigBack)); } TEST(HidlUtils, ConvertInvalidUsage) { AudioUsage invalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioUsageFromHal(kInvalidHalUsage, &invalid)); audio_usage_t halInvalid; EXPECT_EQ(BAD_VALUE, HidlUtils::audioUsageToHal("", &halInvalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioUsageToHal("random string", &halInvalid)); } TEST(HidlUtils, ConvertUsage) { for (const auto enumVal : xsdc_enum_range{}) { const AudioUsage usage = toString(enumVal); audio_usage_t halUsage; AudioUsage usageBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioUsageToHal(usage, &halUsage)) << "Conversion of \"" << usage << "\" failed"; EXPECT_EQ(NO_ERROR, HidlUtils::audioUsageFromHal(halUsage, &usageBack)) << "Conversion of usage " << halUsage << " failed"; EXPECT_EQ(usage, usageBack); } } TEST(HidlUtils, ConvertInvalidOffloadInfo) { AudioOffloadInfo invalid; audio_offload_info_t halInvalid = AUDIO_INFO_INITIALIZER; halInvalid.channel_mask = kInvalidHalChannelMask; halInvalid.format = kInvalidHalFormat; EXPECT_EQ(BAD_VALUE, HidlUtils::audioOffloadInfoFromHal(halInvalid, &invalid)); invalid.base.channelMask = "random string"; invalid.base.format = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioOffloadInfoToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertOffloadInfo) { AudioOffloadInfo offloadInfo = {}; offloadInfo.base = generateValidConfigBase(false /*isInput*/); offloadInfo.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC); offloadInfo.bitRatePerSecond = 320; offloadInfo.durationMicroseconds = -1; offloadInfo.bitWidth = 16; offloadInfo.bufferSize = 1024; offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA); offloadInfo.encapsulationMode = AudioEncapsulationMode::ELEMENTARY_STREAM; offloadInfo.contentId = 42; offloadInfo.syncId = 13; audio_offload_info_t halOffloadInfo; EXPECT_EQ(NO_ERROR, HidlUtils::audioOffloadInfoToHal(offloadInfo, &halOffloadInfo)); AudioOffloadInfo offloadInfoBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioOffloadInfoFromHal(halOffloadInfo, &offloadInfoBack)); EXPECT_EQ(offloadInfo, offloadInfoBack); } TEST(HidlUtils, ConvertInvalidConfig) { AudioConfig invalid; 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 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 = generateValidConfigBase(false /*isInput*/); config.offloadInfo.info( AudioOffloadInfo{.base = config.base, .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC), .bitRatePerSecond = 320, .durationMicroseconds = -1, .bitWidth = 16, .bufferSize = 1024, .usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA), .encapsulationMode = AudioEncapsulationMode::ELEMENTARY_STREAM, .contentId = 42, .syncId = 13}); 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); } TEST(HidlUtils, ConvertInvalidAudioProfile) { AudioProfile invalid; struct audio_profile halInvalid = {}; halInvalid.format = kInvalidHalFormat; halInvalid.num_sample_rates = 0; halInvalid.num_channel_masks = 1; halInvalid.channel_masks[0] = kInvalidHalChannelMask; EXPECT_EQ(BAD_VALUE, HidlUtils::audioProfileFromHal(halInvalid, false /*isInput*/, &invalid)); EXPECT_EQ(BAD_VALUE, HidlUtils::audioProfileFromHal(halInvalid, true /*isInput*/, &invalid)); invalid.format = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioProfileToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertAudioProfile) { AudioProfile profile = {}; profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); profile.sampleRates.resize(2); profile.sampleRates[0] = 44100; profile.sampleRates[1] = 48000; profile.channelMasks.resize(2); profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO); profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); struct audio_profile halProfile; EXPECT_EQ(NO_ERROR, HidlUtils::audioProfileToHal(profile, &halProfile)); AudioProfile profileBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioProfileFromHal(halProfile, false /*isInput*/, &profileBack)); EXPECT_EQ(profile, profileBack); } TEST(HidlUtils, ConvertInvalidAudioPortConfig) { AudioPortConfig invalid; struct audio_port_config halInvalid = {}; halInvalid.type = AUDIO_PORT_TYPE_MIX; halInvalid.role = AUDIO_PORT_ROLE_NONE; // note: this is valid. halInvalid.config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK; halInvalid.channel_mask = kInvalidHalChannelMask; EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortConfigFromHal(halInvalid, &invalid)); invalid.base.channelMask.value("random string"); EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortConfigToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertAudioPortConfig) { AudioPortConfig config = {}; config.id = 42; config.base.sampleRateHz.value(44100); config.base.channelMask.value(toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO)); config.base.format.value(toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT)); config.gain.config({}); config.gain.config().channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); config.ext.device({}); config.ext.device().deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER); struct audio_port_config halConfig; EXPECT_EQ(NO_ERROR, HidlUtils::audioPortConfigToHal(config, &halConfig)); AudioPortConfig configBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioPortConfigFromHal(halConfig, &configBack)); EXPECT_EQ(config, configBack); struct audio_port_config halConfigBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioPortConfigToHal(configBack, &halConfigBack)); EXPECT_TRUE(audio_port_configs_are_equal(&halConfig, &halConfigBack)); } static AudioProfile generateValidAudioProfile() { AudioProfile profile; profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); profile.sampleRates.resize(2); profile.sampleRates[0] = 44100; profile.sampleRates[1] = 48000; profile.channelMasks.resize(2); profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO); profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); return profile; } TEST(HidlUtils, ConvertInvalidAudioTransports) { hidl_vec invalid; struct audio_port_v7 halInvalid = {}; halInvalid.num_audio_profiles = 1; halInvalid.audio_profiles[0].format = kInvalidHalFormat; halInvalid.audio_profiles[0].encapsulation_type = kInvalidEncapsulationType; halInvalid.num_extra_audio_descriptors = 1; halInvalid.extra_audio_descriptors[0].standard = kInvalidAudioStandard; halInvalid.extra_audio_descriptors[0].descriptor_length = EXTRA_AUDIO_DESCRIPTOR_SIZE + 1; EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsFromHal(halInvalid, false /*isInput*/, &invalid)); invalid.resize(2); AudioProfile invalidProfile; invalidProfile.format = "random string"; invalid[0].audioCapability.profile(invalidProfile); invalid[0].encapsulationType = "random string"; invalid[0].audioCapability.edid(hidl_vec(EXTRA_AUDIO_DESCRIPTOR_SIZE + 1)); invalid[1].encapsulationType = "random string"; EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsToHal(invalid, &halInvalid)); // The size of audio profile must not be greater than the maximum value. invalid.resize(0); invalid.resize(AUDIO_PORT_MAX_AUDIO_PROFILES + 1); for (size_t i = 0; i < invalid.size(); ++i) { invalid[i].audioCapability.profile(generateValidAudioProfile()); invalid[i].encapsulationType = toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE); } EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsToHal(invalid, &halInvalid)); // The size of extra audio descriptors must not be greater than the maximum value. invalid.resize(0); invalid.resize(AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS + 1); for (size_t i = 0; i < invalid.size(); ++i) { invalid[i].audioCapability.edid({0x11, 0x06, 0x01}); invalid[i].encapsulationType = toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937); } EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertAudioTransports) { hidl_vec transports; transports.resize(2); transports[0].audioCapability.profile(generateValidAudioProfile()); hidl_vec shortAudioDescriptor({0x11, 0x06, 0x01}); transports[0].encapsulationType = toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE); transports[1].audioCapability.edid(std::move(shortAudioDescriptor)); transports[1].encapsulationType = toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937); struct audio_port_v7 halPort; EXPECT_EQ(NO_ERROR, HidlUtils::audioTransportsToHal(transports, &halPort)); hidl_vec transportsBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioTransportsFromHal(halPort, false /*isInput*/, &transportsBack)); EXPECT_EQ(transports, transportsBack); } TEST(HidlUtils, ConvertInvalidAudioPort) { AudioPort invalid; struct audio_port_v7 halInvalid = {}; halInvalid.type = AUDIO_PORT_TYPE_MIX; halInvalid.role = AUDIO_PORT_ROLE_NONE; // note: this is valid. halInvalid.num_audio_profiles = 1; halInvalid.audio_profiles[0].format = kInvalidHalFormat; EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortFromHal(halInvalid, &invalid)); invalid.transports.resize(1); AudioProfile invalidProfile; invalidProfile.format = "random string"; invalid.transports[0].audioCapability.profile(invalidProfile); EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortToHal(invalid, &halInvalid)); } TEST(HidlUtils, ConvertAudioPort) { AudioPort port = {}; port.id = 42; port.name = "test"; port.transports.resize(2); AudioProfile profile; profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); profile.sampleRates.resize(2); profile.sampleRates[0] = 44100; profile.sampleRates[1] = 48000; profile.channelMasks.resize(2); profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO); profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); port.transports[0].audioCapability.profile(profile); port.transports[0].encapsulationType = toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE); hidl_vec shortAudioDescriptor({0x11, 0x06, 0x01}); port.transports[1].audioCapability.edid(std::move(shortAudioDescriptor)); port.transports[1].encapsulationType = toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937); port.gains.resize(1); port.gains[0].channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO); port.ext.device({}); port.ext.device().deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER); // active config left unspecified. struct audio_port_v7 halPort; EXPECT_EQ(NO_ERROR, HidlUtils::audioPortToHal(port, &halPort)); AudioPort portBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioPortFromHal(halPort, &portBack)); EXPECT_EQ(port, portBack); struct audio_port_v7 halPortBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioPortToHal(portBack, &halPortBack)); EXPECT_TRUE(audio_ports_v7_are_equal(&halPort, &halPortBack)); } TEST(HidlUtils, ConvertInvalidAudioTags) { char halTag[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {}; hidl_vec emptyTag = {{""}}; EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(emptyTag, halTag)); hidl_vec longTag = {{std::string(AUDIO_ATTRIBUTES_TAGS_MAX_SIZE + 1, 'A')}}; EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(longTag, halTag)); hidl_vec tagSeparator = { {std::string(AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1, HidlUtils::sAudioTagSeparator)}}; EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(tagSeparator, halTag)); hidl_vec notExtensions = {{"", "random string", "VX_", "VX_GOOGLE_$$"}}; EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(notExtensions, halTag)); } TEST(HidlUtils, ConvertAudioTags) { hidl_vec emptyTags; char halEmptyTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {}; EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(emptyTags, halEmptyTags)); hidl_vec emptyTagsBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halEmptyTags), &emptyTagsBack)); EXPECT_EQ(emptyTags, emptyTagsBack); hidl_vec oneTag = {{"VX_GOOGLE_VR"}}; char halOneTag[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {}; EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(oneTag, halOneTag)); hidl_vec oneTagBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halOneTag), &oneTagBack)); EXPECT_EQ(oneTag, oneTagBack); hidl_vec 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 twoTagsBack; EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halTwoTags), &twoTagsBack)); EXPECT_EQ(twoTags, twoTagsBack); } template class FilterTest : public ::testing::Test {}; using FilterTestTypeParams = ::testing::Types, std::vector>; TYPED_TEST_SUITE(FilterTest, FilterTestTypeParams); TYPED_TEST(FilterTest, FilterOutNonVendorTags) { TypeParam emptyTags; EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(emptyTags)); // b/248421569, allocate two vendor tags at a time can run out of memory // TypeParam allVendorTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}}; TypeParam allVendorTags1 = {{"VX_GOOGLE_VR_42"}}; EXPECT_EQ(allVendorTags1, HidlUtils::filterOutNonVendorTags(allVendorTags1)); TypeParam allVendorTags2 = {{"VX_GOOGLE_1E100"}}; EXPECT_EQ(allVendorTags2, HidlUtils::filterOutNonVendorTags(allVendorTags2)); 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)); }