blob: 7b7c896fc694607ed3fd70edb9a3579d2ae5f8b3 [file] [log] [blame]
/*
* Copyright (C) 2024 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/AudioControlTestUtils.h"
#include <set>
using android::hardware::automotive::audiocontrol::AudioZone;
using android::hardware::automotive::audiocontrol::AudioZoneConfig;
using android::hardware::automotive::audiocontrol::AudioZoneContext;
using android::hardware::automotive::audiocontrol::AudioZoneContextInfo;
using android::hardware::automotive::audiocontrol::DeviceToContextEntry;
using android::hardware::automotive::audiocontrol::VolumeGroupConfig;
namespace audiomediacommon = android::media::audio::common;
namespace android {
namespace hardware {
namespace audiocontrol {
namespace testutils {
std::string toAlphaNumeric(const std::string& info) {
std::string name = info;
for (size_t i = 0; i < name.size(); i++) {
// gtest test names must only contain alphanumeric characters
if (!std::isalnum(name[i])) name[i] = '_';
}
return name;
}
bool getAudioPortDeviceDescriptor(const audiomediacommon::AudioPort& audioPort,
audiomediacommon::AudioDeviceDescription& description) {
if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) {
return false;
}
const auto& audioDevice =
audioPort.ext.get<audiomediacommon::AudioPortExt::Tag::device>().device;
description = audioDevice.type;
return true;
}
bool getAddressForAudioPort(const android::media::audio::common::AudioPort& audioPort,
std::string& address) {
if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) {
return false;
}
const auto& audioDevice =
audioPort.ext.get<audiomediacommon::AudioPortExt::Tag::device>().device;
switch (audioDevice.address.getTag()) {
case audiomediacommon::AudioDeviceAddress::Tag::id:
address = audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::id>();
return true;
case audiomediacommon::AudioDeviceAddress::Tag::alsa:
address = android::internal::ToString(
audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::alsa>());
return true;
case audiomediacommon::AudioDeviceAddress::Tag::mac:
address = android::internal::ToString(
audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::mac>());
return true;
case audiomediacommon::AudioDeviceAddress::Tag::ipv4:
address = android::internal::ToString(
audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::ipv4>());
return true;
case audiomediacommon::AudioDeviceAddress::Tag::ipv6:
address = android::internal::ToString(
audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::ipv6>());
return true;
default:
address = audioDevice.address.toString();
return true;
}
}
bool getAddressForAudioDevice(const DeviceToContextEntry& device, std::string& address) {
if (device.device.flags.getTag() == audiomediacommon::AudioIoFlags::input ||
device.device.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) {
return false;
}
return getAddressForAudioPort(device.device, address);
}
std::vector<std::string> getDeviceAddressesForVolumeGroup(const VolumeGroupConfig& config) {
std::vector<std::string> addresses;
for (const auto& route : config.carAudioRoutes) {
std::string address;
if (!getAddressForAudioDevice(route, address)) {
continue;
}
addresses.push_back(address);
}
return addresses;
}
std::vector<std::string> getDeviceAddressesForZoneConfig(const AudioZoneConfig& config) {
std::vector<std::string> addresses;
for (const auto& volumeGroup : config.volumeGroups) {
const auto groupAddresses = getDeviceAddressesForVolumeGroup(volumeGroup);
addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end());
}
return addresses;
}
std::vector<std::string> getDeviceAddressesForZone(const AudioZone& config) {
std::vector<std::string> addresses;
for (const auto& zoneConfig : config.audioZoneConfigs) {
const auto groupAddresses = getDeviceAddressesForZoneConfig(zoneConfig);
addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end());
}
return addresses;
}
static void addContextUsages(const AudioZoneContextInfo& info,
std::set<audiomediacommon::AudioUsage>& contextUsages) {
for (const auto& audioAttribute : info.audioAttributes) {
contextUsages.insert(audioAttribute.usage);
}
}
bool contextInfosContainAllAudioAttributeUsages(const std::vector<AudioZoneContextInfo>& infos,
std::string& message) {
static const std::vector<audiomediacommon::AudioUsage> audioUsages{
audiomediacommon::AudioUsage::UNKNOWN,
audiomediacommon::AudioUsage::MEDIA,
audiomediacommon::AudioUsage::VOICE_COMMUNICATION,
audiomediacommon::AudioUsage::VOICE_COMMUNICATION_SIGNALLING,
audiomediacommon::AudioUsage::ALARM,
audiomediacommon::AudioUsage::NOTIFICATION,
audiomediacommon::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE,
audiomediacommon::AudioUsage::NOTIFICATION_EVENT,
audiomediacommon::AudioUsage::ASSISTANCE_ACCESSIBILITY,
audiomediacommon::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE,
audiomediacommon::AudioUsage::ASSISTANCE_SONIFICATION,
audiomediacommon::AudioUsage::GAME,
audiomediacommon::AudioUsage::ASSISTANT,
audiomediacommon::AudioUsage::CALL_ASSISTANT,
audiomediacommon::AudioUsage::EMERGENCY,
audiomediacommon::AudioUsage::SAFETY,
audiomediacommon::AudioUsage::VEHICLE_STATUS,
audiomediacommon::AudioUsage::ANNOUNCEMENT,
};
std::set<audiomediacommon::AudioUsage> contextUsages;
for (const auto& contextInfo : infos) {
addContextUsages(contextInfo, contextUsages);
}
bool allUsagesPresent = true;
for (const auto& usage : audioUsages) {
if (contextUsages.contains(usage)) {
continue;
}
if (message.empty()) {
message = " Missing usage(s): ";
}
message += audiomediacommon::toString(usage) + ", ";
allUsagesPresent = false;
}
return allUsagesPresent;
}
bool contextContainsAllAudioAttributeUsages(const AudioZoneContext& context, std::string& message) {
return contextInfosContainAllAudioAttributeUsages(context.audioContextInfos, message);
}
std::vector<std::string> getContextInfoNamesForAudioRoute(const DeviceToContextEntry& route) {
std::vector<std::string> contextInfoNames;
contextInfoNames.reserve(route.contextNames.size());
for (const auto& contextName : route.contextNames) {
contextInfoNames.push_back(android::internal::ToString(contextName));
}
return contextInfoNames;
}
std::vector<std::string> getContextInfoNamesForVolumeGroup(const VolumeGroupConfig& group) {
std::vector<std::string> contextInfoNames;
for (const auto& route : group.carAudioRoutes) {
std::vector<std::string> routeContexts = getContextInfoNamesForAudioRoute(route);
contextInfoNames.insert(contextInfoNames.begin(), routeContexts.begin(),
routeContexts.end());
}
return contextInfoNames;
}
} // namespace testutils
} // namespace audiocontrol
} // namespace hardware
} // namespace android