xref: /aosp_15_r20/hardware/interfaces/audio/core/all-versions/vts/functional/7.0/Generators.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2021 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 <android-base/macros.h>
18 
19 #include "7.0/Generators.h"
20 #include "7.0/PolicyConfig.h"
21 
22 // clang-format off
23 #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
24 #include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
25 // clang-format on
26 
27 #include PATH(APM_XSD_ENUMS_H_FILENAME)
28 #include PATH(APM_XSD_H_FILENAME)
29 
30 // Forward declaration for functions that are substituted
31 // in generator unit tests.
32 const PolicyConfig& getCachedPolicyConfig();
33 const std::vector<DeviceParameter>& getDeviceParameters();
34 
35 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
36 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
37 namespace xsd {
38 using namespace ::android::audio::policy::configuration::CPP_VERSION;
39 }
40 
combineAudioConfig(std::vector<xsd::AudioChannelMask> channelMasks,std::vector<int64_t> sampleRates,const std::string & format)41 static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannelMask> channelMasks,
42                                                    std::vector<int64_t> sampleRates,
43                                                    const std::string& format) {
44     std::vector<AudioConfig> configs;
45     configs.reserve(channelMasks.size() * sampleRates.size());
46     for (auto channelMask : channelMasks) {
47         for (auto sampleRate : sampleRates) {
48             AudioConfig config{};
49             config.base.channelMask = toString(channelMask);
50             config.base.sampleRateHz = sampleRate;
51             config.base.format = format;
52             configs.push_back(config);
53         }
54     }
55     return configs;
56 }
57 
generateOutFlags(const xsd::MixPorts::MixPort & mixPort)58 static std::tuple<std::vector<AudioInOutFlag>, bool> generateOutFlags(
59         const xsd::MixPorts::MixPort& mixPort) {
60     std::vector<AudioInOutFlag> flags;
61     bool isOffload = false;
62     if (mixPort.hasFlags()) {
63         auto xsdFlags = mixPort.getFlags();
64         isOffload = std::find(xsdFlags.begin(), xsdFlags.end(),
65                               xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
66                     xsdFlags.end();
67         for (auto flag : xsdFlags) {
68             if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
69                 flags.push_back(toString(flag));
70             }
71         }
72     }
73     return {flags, isOffload};
74 }
75 
generateOffloadInfo(const AudioConfigBase & base)76 static AudioOffloadInfo generateOffloadInfo(const AudioConfigBase& base) {
77     return AudioOffloadInfo{
78             .base = base,
79             .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC),
80             .usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
81             .bitRatePerSecond = 192,  // as in sine882hz3s.mp3
82             .durationMicroseconds = -1,
83             .bitWidth = 16,
84             .bufferSize = 72000  // 3 seconds at 192 kbps, as in sine882hz3s.mp3
85     };
86 }
87 
generateOutputDeviceConfigParameters(bool oneProfilePerDevice)88 std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
89     std::vector<DeviceConfigParameter> result;
90     for (const auto& device : getDeviceParameters()) {
91         const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
92         auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
93         if (!module || !module->getFirstMixPorts()) break;
94         for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
95             if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
96             const auto attachedDeviceAddress =
97                     getCachedPolicyConfig().getDeviceAddressOfSinkDeviceAttachedToMixPort(
98                             moduleName, mixPort.getName());
99             if (!attachedDeviceAddress.has_value()) continue;
100             auto [flags, isOffload] = generateOutFlags(mixPort);
101             for (const auto& profile : mixPort.getProfile()) {
102                 if (!profile.hasFormat() || !profile.hasSamplingRates() ||
103                     !profile.hasChannelMasks())
104                     continue;
105                 auto configs = combineAudioConfig(profile.getChannelMasks(),
106                                                   profile.getSamplingRates(), profile.getFormat());
107                 for (auto& config : configs) {
108                     // Some combinations of flags declared in the config file require special
109                     // treatment.
110                     if (isOffload) {
111                         config.offloadInfo.info(generateOffloadInfo(config.base));
112                     }
113                     result.emplace_back(device, mixPort.getName(), attachedDeviceAddress.value(),
114                                         config, flags);
115                     if (oneProfilePerDevice) break;
116                 }
117                 if (oneProfilePerDevice) break;
118             }
119             if (oneProfilePerDevice) break;
120         }
121     }
122     return result;
123 }
124 
getOutputDeviceConfigParameters()125 const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
126     static std::vector<DeviceConfigParameter> parameters =
127             generateOutputDeviceConfigParameters(false);
128     return parameters;
129 }
130 
getOutputDeviceSingleConfigParameters()131 const std::vector<DeviceConfigParameter>& getOutputDeviceSingleConfigParameters() {
132     static std::vector<DeviceConfigParameter> parameters =
133             generateOutputDeviceConfigParameters(true);
134     return parameters;
135 }
136 
getOutputDeviceInvalidConfigParameters(bool generateInvalidFlags)137 const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters(
138         bool generateInvalidFlags) {
139     static std::vector<DeviceConfigParameter> parameters = [&] {
140         std::vector<DeviceConfigParameter> result;
141         for (const auto& device : getDeviceParameters()) {
142             auto module =
143                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
144             if (!module || !module->getFirstMixPorts()) break;
145             bool hasRegularConfig = false, hasOffloadConfig = false;
146             for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
147                 if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
148                 auto [validFlags, isOffload] = generateOutFlags(mixPort);
149                 if ((!isOffload && hasRegularConfig) || (isOffload && hasOffloadConfig)) continue;
150                 for (const auto& profile : mixPort.getProfile()) {
151                     if (!profile.hasFormat() || !profile.hasSamplingRates() ||
152                         !profile.hasChannelMasks())
153                         continue;
154                     AudioConfigBase validBase = {
155                             profile.getFormat(),
156                             static_cast<uint32_t>(profile.getSamplingRates()[0]),
157                             toString(profile.getChannelMasks()[0])};
158                     DeviceAddress defaultDevice = {
159                             toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT), {}};
160                     {
161                         AudioConfig config{.base = validBase};
162                         config.base.channelMask = "random_string";
163                         if (isOffload) {
164                             config.offloadInfo.info(generateOffloadInfo(validBase));
165                         }
166                         result.emplace_back(device, mixPort.getName(), defaultDevice, config,
167                                             validFlags);
168                     }
169                     {
170                         AudioConfig config{.base = validBase};
171                         config.base.format = "random_string";
172                         if (isOffload) {
173                             config.offloadInfo.info(generateOffloadInfo(validBase));
174                         }
175                         result.emplace_back(device, mixPort.getName(), defaultDevice, config,
176                                             validFlags);
177                     }
178                     if (generateInvalidFlags) {
179                         AudioConfig config{.base = validBase};
180                         if (isOffload) {
181                             config.offloadInfo.info(generateOffloadInfo(validBase));
182                         }
183                         std::vector<AudioInOutFlag> flags = {"random_string", ""};
184                         result.emplace_back(device, mixPort.getName(), defaultDevice, config,
185                                             flags);
186                     }
187                     if (isOffload) {
188                         {
189                             AudioConfig config{.base = validBase};
190                             config.offloadInfo.info(generateOffloadInfo(validBase));
191                             config.offloadInfo.info().base.channelMask = "random_string";
192                             result.emplace_back(device, mixPort.getName(), defaultDevice, config,
193                                                 validFlags);
194                         }
195                         {
196                             AudioConfig config{.base = validBase};
197                             config.offloadInfo.info(generateOffloadInfo(validBase));
198                             config.offloadInfo.info().base.format = "random_string";
199                             result.emplace_back(device, mixPort.getName(), defaultDevice, config,
200                                                 validFlags);
201                         }
202                         {
203                             AudioConfig config{.base = validBase};
204                             config.offloadInfo.info(generateOffloadInfo(validBase));
205                             config.offloadInfo.info().streamType = "random_string";
206                             result.emplace_back(device, mixPort.getName(), defaultDevice, config,
207                                                 validFlags);
208                         }
209                         {
210                             AudioConfig config{.base = validBase};
211                             config.offloadInfo.info(generateOffloadInfo(validBase));
212                             config.offloadInfo.info().usage = "random_string";
213                             result.emplace_back(device, mixPort.getName(), defaultDevice, config,
214                                                 validFlags);
215                         }
216                         hasOffloadConfig = true;
217                     } else {
218                         hasRegularConfig = true;
219                     }
220                     break;
221                 }
222                 if (hasOffloadConfig && hasRegularConfig) break;
223             }
224         }
225         return result;
226     }();
227     return parameters;
228 }
229 
generateInputDeviceConfigParameters(bool oneProfilePerDevice)230 std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneProfilePerDevice) {
231     std::vector<DeviceConfigParameter> result;
232     for (const auto& device : getDeviceParameters()) {
233         const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
234         auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
235         if (!module || !module->getFirstMixPorts()) break;
236         for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
237             if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
238             const auto attachedDeviceAddress =
239                     getCachedPolicyConfig().getDeviceAddressOfSourceDeviceAttachedToMixPort(
240                             moduleName, mixPort.getName());
241             if (!attachedDeviceAddress.has_value()) continue;
242             std::vector<AudioInOutFlag> flags;
243             if (mixPort.hasFlags()) {
244                 std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
245                                std::back_inserter(flags), [](auto flag) { return toString(flag); });
246             }
247             for (const auto& profile : mixPort.getProfile()) {
248                 if (!profile.hasFormat() || !profile.hasSamplingRates() ||
249                     !profile.hasChannelMasks())
250                     continue;
251                 auto configs = combineAudioConfig(profile.getChannelMasks(),
252                                                   profile.getSamplingRates(), profile.getFormat());
253                 for (const auto& config : configs) {
254                     result.emplace_back(device, mixPort.getName(), attachedDeviceAddress.value(),
255                                         config, flags);
256                     if (oneProfilePerDevice) break;
257                 }
258                 if (oneProfilePerDevice) break;
259             }
260             if (oneProfilePerDevice) break;
261         }
262     }
263     return result;
264 }
265 
getInputDeviceConfigParameters()266 const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
267     static std::vector<DeviceConfigParameter> parameters =
268             generateInputDeviceConfigParameters(false);
269     return parameters;
270 }
271 
getInputDeviceSingleConfigParameters()272 const std::vector<DeviceConfigParameter>& getInputDeviceSingleConfigParameters() {
273     static std::vector<DeviceConfigParameter> parameters =
274             generateInputDeviceConfigParameters(true);
275     return parameters;
276 }
277 
getInputDeviceInvalidConfigParameters(bool generateInvalidFlags)278 const std::vector<DeviceConfigParameter>& getInputDeviceInvalidConfigParameters(
279         bool generateInvalidFlags) {
280     static std::vector<DeviceConfigParameter> parameters = [&] {
281         std::vector<DeviceConfigParameter> result;
282         for (const auto& device : getDeviceParameters()) {
283             auto module =
284                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
285             if (!module || !module->getFirstMixPorts()) break;
286             bool hasConfig = false;
287             for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
288                 if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
289                 std::vector<AudioInOutFlag> validFlags;
290                 if (mixPort.hasFlags()) {
291                     std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
292                                    std::back_inserter(validFlags),
293                                    [](auto flag) { return toString(flag); });
294                 }
295                 for (const auto& profile : mixPort.getProfile()) {
296                     if (!profile.hasFormat() || !profile.hasSamplingRates() ||
297                         !profile.hasChannelMasks())
298                         continue;
299                     AudioConfigBase validBase = {
300                             profile.getFormat(),
301                             static_cast<uint32_t>(profile.getSamplingRates()[0]),
302                             toString(profile.getChannelMasks()[0])};
303                     DeviceAddress defaultDevice = {
304                             toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT), {}};
305                     {
306                         AudioConfig config{.base = validBase};
307                         config.base.channelMask = "random_string";
308                         result.emplace_back(device, mixPort.getName(), defaultDevice, config,
309                                             validFlags);
310                     }
311                     {
312                         AudioConfig config{.base = validBase};
313                         config.base.format = "random_string";
314                         result.emplace_back(device, mixPort.getName(), defaultDevice, config,
315                                             validFlags);
316                     }
317                     if (generateInvalidFlags) {
318                         AudioConfig config{.base = validBase};
319                         std::vector<AudioInOutFlag> flags = {"random_string", ""};
320                         result.emplace_back(device, mixPort.getName(), defaultDevice, config,
321                                             flags);
322                     }
323                     hasConfig = true;
324                     break;
325                 }
326                 if (hasConfig) break;
327             }
328         }
329         return result;
330     }();
331     return parameters;
332 }
333