xref: /aosp_15_r20/hardware/interfaces/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "../include/AudioControlTestUtils.h"
18 
19 #include <set>
20 
21 using android::hardware::automotive::audiocontrol::AudioZone;
22 using android::hardware::automotive::audiocontrol::AudioZoneConfig;
23 using android::hardware::automotive::audiocontrol::AudioZoneContext;
24 using android::hardware::automotive::audiocontrol::AudioZoneContextInfo;
25 using android::hardware::automotive::audiocontrol::DeviceToContextEntry;
26 using android::hardware::automotive::audiocontrol::VolumeGroupConfig;
27 
28 namespace audiomediacommon = android::media::audio::common;
29 
30 namespace android {
31 namespace hardware {
32 namespace audiocontrol {
33 namespace testutils {
34 
toAlphaNumeric(const std::string & info)35 std::string toAlphaNumeric(const std::string& info) {
36     std::string name = info;
37     for (size_t i = 0; i < name.size(); i++) {
38         // gtest test names must only contain alphanumeric characters
39         if (!std::isalnum(name[i])) name[i] = '_';
40     }
41 
42     return name;
43 }
44 
getAudioPortDeviceDescriptor(const audiomediacommon::AudioPort & audioPort,audiomediacommon::AudioDeviceDescription & description)45 bool getAudioPortDeviceDescriptor(const audiomediacommon::AudioPort& audioPort,
46                                   audiomediacommon::AudioDeviceDescription& description) {
47     if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) {
48         return false;
49     }
50     const auto& audioDevice =
51             audioPort.ext.get<audiomediacommon::AudioPortExt::Tag::device>().device;
52     description = audioDevice.type;
53     return true;
54 }
55 
getAddressForAudioPort(const android::media::audio::common::AudioPort & audioPort,std::string & address)56 bool getAddressForAudioPort(const android::media::audio::common::AudioPort& audioPort,
57                             std::string& address) {
58     if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) {
59         return false;
60     }
61     const auto& audioDevice =
62             audioPort.ext.get<audiomediacommon::AudioPortExt::Tag::device>().device;
63 
64     switch (audioDevice.address.getTag()) {
65         case audiomediacommon::AudioDeviceAddress::Tag::id:
66             address = audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::id>();
67             return true;
68         case audiomediacommon::AudioDeviceAddress::Tag::alsa:
69             address = android::internal::ToString(
70                     audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::alsa>());
71             return true;
72         case audiomediacommon::AudioDeviceAddress::Tag::mac:
73             address = android::internal::ToString(
74                     audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::mac>());
75             return true;
76         case audiomediacommon::AudioDeviceAddress::Tag::ipv4:
77             address = android::internal::ToString(
78                     audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::ipv4>());
79             return true;
80         case audiomediacommon::AudioDeviceAddress::Tag::ipv6:
81             address = android::internal::ToString(
82                     audioDevice.address.get<audiomediacommon::AudioDeviceAddress::Tag::ipv6>());
83             return true;
84         default:
85             address = audioDevice.address.toString();
86             return true;
87     }
88 }
89 
getAddressForAudioDevice(const DeviceToContextEntry & device,std::string & address)90 bool getAddressForAudioDevice(const DeviceToContextEntry& device, std::string& address) {
91     if (device.device.flags.getTag() == audiomediacommon::AudioIoFlags::input ||
92         device.device.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) {
93         return false;
94     }
95     return getAddressForAudioPort(device.device, address);
96 }
97 
getDeviceAddressesForVolumeGroup(const VolumeGroupConfig & config)98 std::vector<std::string> getDeviceAddressesForVolumeGroup(const VolumeGroupConfig& config) {
99     std::vector<std::string> addresses;
100     for (const auto& route : config.carAudioRoutes) {
101         std::string address;
102         if (!getAddressForAudioDevice(route, address)) {
103             continue;
104         }
105         addresses.push_back(address);
106     }
107     return addresses;
108 }
109 
getDeviceAddressesForZoneConfig(const AudioZoneConfig & config)110 std::vector<std::string> getDeviceAddressesForZoneConfig(const AudioZoneConfig& config) {
111     std::vector<std::string> addresses;
112     for (const auto& volumeGroup : config.volumeGroups) {
113         const auto groupAddresses = getDeviceAddressesForVolumeGroup(volumeGroup);
114         addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end());
115     }
116     return addresses;
117 }
118 
getDeviceAddressesForZone(const AudioZone & config)119 std::vector<std::string> getDeviceAddressesForZone(const AudioZone& config) {
120     std::vector<std::string> addresses;
121     for (const auto& zoneConfig : config.audioZoneConfigs) {
122         const auto groupAddresses = getDeviceAddressesForZoneConfig(zoneConfig);
123         addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end());
124     }
125     return addresses;
126 }
127 
addContextUsages(const AudioZoneContextInfo & info,std::set<audiomediacommon::AudioUsage> & contextUsages)128 static void addContextUsages(const AudioZoneContextInfo& info,
129                              std::set<audiomediacommon::AudioUsage>& contextUsages) {
130     for (const auto& audioAttribute : info.audioAttributes) {
131         contextUsages.insert(audioAttribute.usage);
132     }
133 }
134 
contextInfosContainAllAudioAttributeUsages(const std::vector<AudioZoneContextInfo> & infos,std::string & message)135 bool contextInfosContainAllAudioAttributeUsages(const std::vector<AudioZoneContextInfo>& infos,
136                                                 std::string& message) {
137     static const std::vector<audiomediacommon::AudioUsage> audioUsages{
138             audiomediacommon::AudioUsage::UNKNOWN,
139             audiomediacommon::AudioUsage::MEDIA,
140             audiomediacommon::AudioUsage::VOICE_COMMUNICATION,
141             audiomediacommon::AudioUsage::VOICE_COMMUNICATION_SIGNALLING,
142             audiomediacommon::AudioUsage::ALARM,
143             audiomediacommon::AudioUsage::NOTIFICATION,
144             audiomediacommon::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE,
145             audiomediacommon::AudioUsage::NOTIFICATION_EVENT,
146             audiomediacommon::AudioUsage::ASSISTANCE_ACCESSIBILITY,
147             audiomediacommon::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE,
148             audiomediacommon::AudioUsage::ASSISTANCE_SONIFICATION,
149             audiomediacommon::AudioUsage::GAME,
150             audiomediacommon::AudioUsage::ASSISTANT,
151             audiomediacommon::AudioUsage::CALL_ASSISTANT,
152             audiomediacommon::AudioUsage::EMERGENCY,
153             audiomediacommon::AudioUsage::SAFETY,
154             audiomediacommon::AudioUsage::VEHICLE_STATUS,
155             audiomediacommon::AudioUsage::ANNOUNCEMENT,
156     };
157 
158     std::set<audiomediacommon::AudioUsage> contextUsages;
159     for (const auto& contextInfo : infos) {
160         addContextUsages(contextInfo, contextUsages);
161     }
162 
163     bool allUsagesPresent = true;
164     for (const auto& usage : audioUsages) {
165         if (contextUsages.contains(usage)) {
166             continue;
167         }
168         if (message.empty()) {
169             message = " Missing usage(s): ";
170         }
171         message += audiomediacommon::toString(usage) + ", ";
172         allUsagesPresent = false;
173     }
174     return allUsagesPresent;
175 }
176 
contextContainsAllAudioAttributeUsages(const AudioZoneContext & context,std::string & message)177 bool contextContainsAllAudioAttributeUsages(const AudioZoneContext& context, std::string& message) {
178     return contextInfosContainAllAudioAttributeUsages(context.audioContextInfos, message);
179 }
180 
getContextInfoNamesForAudioRoute(const DeviceToContextEntry & route)181 std::vector<std::string> getContextInfoNamesForAudioRoute(const DeviceToContextEntry& route) {
182     std::vector<std::string> contextInfoNames;
183     contextInfoNames.reserve(route.contextNames.size());
184     for (const auto& contextName : route.contextNames) {
185         contextInfoNames.push_back(android::internal::ToString(contextName));
186     }
187     return contextInfoNames;
188 }
189 
getContextInfoNamesForVolumeGroup(const VolumeGroupConfig & group)190 std::vector<std::string> getContextInfoNamesForVolumeGroup(const VolumeGroupConfig& group) {
191     std::vector<std::string> contextInfoNames;
192     for (const auto& route : group.carAudioRoutes) {
193         std::vector<std::string> routeContexts = getContextInfoNamesForAudioRoute(route);
194         contextInfoNames.insert(contextInfoNames.begin(), routeContexts.begin(),
195                                 routeContexts.end());
196     }
197     return contextInfoNames;
198 }
199 
200 }  // namespace testutils
201 }  // namespace audiocontrol
202 }  // namespace hardware
203 }  // namespace android