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