• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/FILE_VERSION/types.h)
24 #include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
25 // clang-format on
26 
27 #include <android_audio_policy_configuration_V7_0-enums.h>
28 #include <android_audio_policy_configuration_V7_0.h>
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::CPP_VERSION;
36 using namespace ::android::hardware::audio::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     static const std::vector<AudioInOutFlag> offloadFlags = {
61             toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
62             toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)};
63     std::vector<AudioInOutFlag> flags;
64     bool isOffload = false;
65     if (mixPort.hasFlags()) {
66         auto xsdFlags = mixPort.getFlags();
67         isOffload = std::find(xsdFlags.begin(), xsdFlags.end(),
68                               xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
69                     xsdFlags.end();
70         if (!isOffload) {
71             for (auto flag : xsdFlags) {
72                 if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
73                     flags.push_back(toString(flag));
74                 }
75             }
76         } else {
77             flags = offloadFlags;
78         }
79     }
80     return {flags, isOffload};
81 }
82 
generateOffloadInfo(const AudioConfigBase & base)83 static AudioOffloadInfo generateOffloadInfo(const AudioConfigBase& base) {
84     return AudioOffloadInfo{
85             .base = base,
86             .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC),
87             .usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
88             .bitRatePerSecond = 320,
89             .durationMicroseconds = -1,
90             .bitWidth = 16,
91             .bufferSize = 256  // arbitrary value
92     };
93 }
94 
generateOutputDeviceConfigParameters(bool oneProfilePerDevice)95 std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
96     std::vector<DeviceConfigParameter> result;
97     for (const auto& device : getDeviceParameters()) {
98         auto module =
99                 getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
100         if (!module || !module->getFirstMixPorts()) break;
101         for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
102             if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
103             auto [flags, isOffload] = generateOutFlags(mixPort);
104             for (const auto& profile : mixPort.getProfile()) {
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(), config, flags);
114                     if (oneProfilePerDevice) break;
115                 }
116                 if (oneProfilePerDevice) break;
117             }
118             if (oneProfilePerDevice) break;
119         }
120     }
121     return result;
122 }
123 
getOutputDeviceConfigParameters()124 const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
125     static std::vector<DeviceConfigParameter> parameters =
126             generateOutputDeviceConfigParameters(false);
127     return parameters;
128 }
129 
getOutputDeviceSingleConfigParameters()130 const std::vector<DeviceConfigParameter>& getOutputDeviceSingleConfigParameters() {
131     static std::vector<DeviceConfigParameter> parameters =
132             generateOutputDeviceConfigParameters(true);
133     return parameters;
134 }
135 
getOutputDeviceInvalidConfigParameters(bool generateInvalidFlags)136 const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters(
137         bool generateInvalidFlags) {
138     static std::vector<DeviceConfigParameter> parameters = [&] {
139         std::vector<DeviceConfigParameter> result;
140         for (const auto& device : getDeviceParameters()) {
141             auto module =
142                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
143             if (!module || !module->getFirstMixPorts()) break;
144             bool hasRegularConfig = false, hasOffloadConfig = false;
145             for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
146                 if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
147                 auto [validFlags, isOffload] = generateOutFlags(mixPort);
148                 if ((!isOffload && hasRegularConfig) || (isOffload && hasOffloadConfig)) continue;
149                 for (const auto& profile : mixPort.getProfile()) {
150                     if (!profile.hasFormat() || !profile.hasSamplingRates() ||
151                         !profile.hasChannelMasks())
152                         continue;
153                     AudioConfigBase validBase = {
154                             profile.getFormat(),
155                             static_cast<uint32_t>(profile.getSamplingRates()[0]),
156                             toString(profile.getChannelMasks()[0])};
157                     {
158                         AudioConfig config{.base = validBase};
159                         config.base.channelMask = "random_string";
160                         if (isOffload) {
161                             config.offloadInfo.info(generateOffloadInfo(validBase));
162                         }
163                         result.emplace_back(device, mixPort.getName(), config, validFlags);
164                     }
165                     {
166                         AudioConfig config{.base = validBase};
167                         config.base.format = "random_string";
168                         if (isOffload) {
169                             config.offloadInfo.info(generateOffloadInfo(validBase));
170                         }
171                         result.emplace_back(device, mixPort.getName(), config, validFlags);
172                     }
173                     if (generateInvalidFlags) {
174                         AudioConfig config{.base = validBase};
175                         if (isOffload) {
176                             config.offloadInfo.info(generateOffloadInfo(validBase));
177                         }
178                         std::vector<AudioInOutFlag> flags = {"random_string", ""};
179                         result.emplace_back(device, mixPort.getName(), config, flags);
180                     }
181                     if (isOffload) {
182                         {
183                             AudioConfig config{.base = validBase};
184                             config.offloadInfo.info(generateOffloadInfo(validBase));
185                             config.offloadInfo.info().base.channelMask = "random_string";
186                             result.emplace_back(device, mixPort.getName(), config, validFlags);
187                         }
188                         {
189                             AudioConfig config{.base = validBase};
190                             config.offloadInfo.info(generateOffloadInfo(validBase));
191                             config.offloadInfo.info().base.format = "random_string";
192                             result.emplace_back(device, mixPort.getName(), config, validFlags);
193                         }
194                         {
195                             AudioConfig config{.base = validBase};
196                             config.offloadInfo.info(generateOffloadInfo(validBase));
197                             config.offloadInfo.info().streamType = "random_string";
198                             result.emplace_back(device, mixPort.getName(), config, validFlags);
199                         }
200                         {
201                             AudioConfig config{.base = validBase};
202                             config.offloadInfo.info(generateOffloadInfo(validBase));
203                             config.offloadInfo.info().usage = "random_string";
204                             result.emplace_back(device, mixPort.getName(), config, validFlags);
205                         }
206                         hasOffloadConfig = true;
207                     } else {
208                         hasRegularConfig = true;
209                     }
210                     break;
211                 }
212                 if (hasOffloadConfig && hasRegularConfig) break;
213             }
214         }
215         return result;
216     }();
217     return parameters;
218 }
219 
generateInputDeviceConfigParameters(bool oneProfilePerDevice)220 std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneProfilePerDevice) {
221     std::vector<DeviceConfigParameter> result;
222     for (const auto& device : getDeviceParameters()) {
223         auto module =
224                 getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
225         if (!module || !module->getFirstMixPorts()) break;
226         for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
227             if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
228             std::vector<AudioInOutFlag> flags;
229             if (mixPort.hasFlags()) {
230                 std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
231                                std::back_inserter(flags), [](auto flag) { return toString(flag); });
232             }
233             for (const auto& profile : mixPort.getProfile()) {
234                 auto configs = combineAudioConfig(profile.getChannelMasks(),
235                                                   profile.getSamplingRates(), profile.getFormat());
236                 for (const auto& config : configs) {
237                     result.emplace_back(device, mixPort.getName(), config, flags);
238                     if (oneProfilePerDevice) break;
239                 }
240                 if (oneProfilePerDevice) break;
241             }
242             if (oneProfilePerDevice) break;
243         }
244     }
245     return result;
246 }
247 
getInputDeviceConfigParameters()248 const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
249     static std::vector<DeviceConfigParameter> parameters =
250             generateInputDeviceConfigParameters(false);
251     return parameters;
252 }
253 
getInputDeviceSingleConfigParameters()254 const std::vector<DeviceConfigParameter>& getInputDeviceSingleConfigParameters() {
255     static std::vector<DeviceConfigParameter> parameters =
256             generateInputDeviceConfigParameters(true);
257     return parameters;
258 }
259 
getInputDeviceInvalidConfigParameters(bool generateInvalidFlags)260 const std::vector<DeviceConfigParameter>& getInputDeviceInvalidConfigParameters(
261         bool generateInvalidFlags) {
262     static std::vector<DeviceConfigParameter> parameters = [&] {
263         std::vector<DeviceConfigParameter> result;
264         for (const auto& device : getDeviceParameters()) {
265             auto module =
266                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
267             if (!module || !module->getFirstMixPorts()) break;
268             bool hasConfig = false;
269             for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
270                 if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
271                 std::vector<AudioInOutFlag> validFlags;
272                 if (mixPort.hasFlags()) {
273                     std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
274                                    std::back_inserter(validFlags),
275                                    [](auto flag) { return toString(flag); });
276                 }
277                 for (const auto& profile : mixPort.getProfile()) {
278                     if (!profile.hasFormat() || !profile.hasSamplingRates() ||
279                         !profile.hasChannelMasks())
280                         continue;
281                     AudioConfigBase validBase = {
282                             profile.getFormat(),
283                             static_cast<uint32_t>(profile.getSamplingRates()[0]),
284                             toString(profile.getChannelMasks()[0])};
285                     {
286                         AudioConfig config{.base = validBase};
287                         config.base.channelMask = "random_string";
288                         result.emplace_back(device, mixPort.getName(), config, validFlags);
289                     }
290                     {
291                         AudioConfig config{.base = validBase};
292                         config.base.format = "random_string";
293                         result.emplace_back(device, mixPort.getName(), config, validFlags);
294                     }
295                     if (generateInvalidFlags) {
296                         AudioConfig config{.base = validBase};
297                         std::vector<AudioInOutFlag> flags = {"random_string", ""};
298                         result.emplace_back(device, mixPort.getName(), config, flags);
299                     }
300                     hasConfig = true;
301                     break;
302                 }
303                 if (hasConfig) break;
304             }
305         }
306         return result;
307     }();
308     return parameters;
309 }
310