1 /*
2  * Copyright (C) 2022 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 <Utils.h>
18 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
19 #include <aidl/android/media/audio/common/AudioDeviceType.h>
20 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
21 #include <aidl/android/media/audio/common/AudioFormatType.h>
22 #include <aidl/android/media/audio/common/AudioIoFlags.h>
23 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
24 #include <media/stagefright/foundation/MediaDefs.h>
25 
26 #include "core-impl/Configuration.h"
27 
28 using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
29 using aidl::android::media::audio::common::AudioChannelLayout;
30 using aidl::android::media::audio::common::AudioDeviceDescription;
31 using aidl::android::media::audio::common::AudioDeviceType;
32 using aidl::android::media::audio::common::AudioFormatDescription;
33 using aidl::android::media::audio::common::AudioFormatType;
34 using aidl::android::media::audio::common::AudioGainConfig;
35 using aidl::android::media::audio::common::AudioIoFlags;
36 using aidl::android::media::audio::common::AudioOutputFlags;
37 using aidl::android::media::audio::common::AudioPort;
38 using aidl::android::media::audio::common::AudioPortConfig;
39 using aidl::android::media::audio::common::AudioPortDeviceExt;
40 using aidl::android::media::audio::common::AudioPortExt;
41 using aidl::android::media::audio::common::AudioPortMixExt;
42 using aidl::android::media::audio::common::AudioProfile;
43 using aidl::android::media::audio::common::Int;
44 using aidl::android::media::audio::common::PcmType;
45 using Configuration = aidl::android::hardware::audio::core::Module::Configuration;
46 
47 namespace aidl::android::hardware::audio::core::internal {
48 
fillProfile(AudioProfile * profile,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)49 static void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
50                         const std::vector<int32_t>& sampleRates) {
51     for (auto layout : channelLayouts) {
52         profile->channelMasks.push_back(
53                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
54     }
55     profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
56 }
57 
createProfile(PcmType pcmType,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)58 static AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
59                                   const std::vector<int32_t>& sampleRates) {
60     AudioProfile profile;
61     profile.format.type = AudioFormatType::PCM;
62     profile.format.pcm = pcmType;
63     fillProfile(&profile, channelLayouts, sampleRates);
64     return profile;
65 }
66 
createProfile(const std::string & encodingType,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)67 static AudioProfile createProfile(const std::string& encodingType,
68                                   const std::vector<int32_t>& channelLayouts,
69                                   const std::vector<int32_t>& sampleRates) {
70     AudioProfile profile;
71     profile.format.encoding = encodingType;
72     fillProfile(&profile, channelLayouts, sampleRates);
73     return profile;
74 }
75 
createDeviceExt(AudioDeviceType devType,int32_t flags,std::string connection="")76 static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags,
77                                     std::string connection = "") {
78     AudioPortDeviceExt deviceExt;
79     deviceExt.device.type.type = devType;
80     if (devType == AudioDeviceType::IN_MICROPHONE && connection.empty()) {
81         deviceExt.device.address = "bottom";
82     } else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
83         deviceExt.device.address = "back";
84     }
85     deviceExt.device.type.connection = std::move(connection);
86     deviceExt.flags = flags;
87     return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
88 }
89 
createPortMixExt(int32_t maxOpenStreamCount,int32_t maxActiveStreamCount)90 static AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
91     AudioPortMixExt mixExt;
92     mixExt.maxOpenStreamCount = maxOpenStreamCount;
93     mixExt.maxActiveStreamCount = maxActiveStreamCount;
94     return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
95 }
96 
createPort(int32_t id,const std::string & name,int32_t flags,bool isInput,const AudioPortExt & ext)97 static AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
98                             const AudioPortExt& ext) {
99     AudioPort port;
100     port.id = id;
101     port.name = name;
102     port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
103                          : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
104     port.ext = ext;
105     return port;
106 }
107 
createDynamicPortConfig(int32_t id,int32_t portId,int32_t flags,bool isInput,const AudioPortExt & ext)108 static AudioPortConfig createDynamicPortConfig(int32_t id, int32_t portId, int32_t flags,
109                                                bool isInput, const AudioPortExt& ext) {
110     AudioPortConfig config;
111     config.id = id;
112     config.portId = portId;
113     config.format = AudioFormatDescription{};
114     config.channelMask = AudioChannelLayout{};
115     config.sampleRate = Int{.value = 0};
116     config.gain = AudioGainConfig();
117     config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
118                            : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
119     config.ext = ext;
120     return config;
121 }
122 
createPortConfig(int32_t id,int32_t portId,PcmType pcmType,int32_t layout,int32_t sampleRate,int32_t flags,bool isInput,const AudioPortExt & ext)123 static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
124                                         int32_t sampleRate, int32_t flags, bool isInput,
125                                         const AudioPortExt& ext) {
126     AudioPortConfig config = createDynamicPortConfig(id, portId, flags, isInput, ext);
127     config.sampleRate = Int{.value = sampleRate};
128     config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
129     config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
130     return config;
131 }
132 
createRoute(const std::vector<AudioPort> & sources,const AudioPort & sink)133 static AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
134     AudioRoute route;
135     route.sinkPortId = sink.id;
136     std::transform(sources.begin(), sources.end(), std::back_inserter(route.sourcePortIds),
137                    [](const auto& port) { return port.id; });
138     return route;
139 }
140 
getStandard16And24BitPcmAudioProfiles()141 std::vector<AudioProfile> getStandard16And24BitPcmAudioProfiles() {
142     auto createStdPcmAudioProfile = [](const PcmType& pcmType) {
143         return AudioProfile{
144                 .format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType},
145                 .channelMasks = {AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
146                                          AudioChannelLayout::LAYOUT_MONO),
147                                  AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
148                                          AudioChannelLayout::LAYOUT_STEREO)},
149                 .sampleRates = {8000, 11025, 16000, 32000, 44100, 48000}};
150     };
151     return {
152             createStdPcmAudioProfile(PcmType::INT_16_BIT),
153             createStdPcmAudioProfile(PcmType::INT_24_BIT),
154     };
155 }
156 
157 // Primary (default) configuration:
158 //
159 // Device ports:
160 //  * "Speaker", OUT_SPEAKER, default
161 //    - no profiles specified
162 //  * "Built-In Mic", IN_MICROPHONE, default
163 //    - no profiles specified
164 //  * "Telephony Tx", OUT_TELEPHONY_TX
165 //    - no profiles specified
166 //  * "Telephony Rx", IN_TELEPHONY_RX
167 //    - no profiles specified
168 //  * "FM Tuner", IN_FM_TUNER
169 //    - no profiles specified
170 //
171 // Mix ports:
172 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
173 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
174 //  * "primary input", 1 max open, 1 max active stream
175 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
176 //  * "telephony_tx", 1 max open, 1 max active stream
177 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
178 //  * "telephony_rx", 1 max open, 1 max active stream
179 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
180 //  * "fm_tuner", 1 max open, 1 max active stream
181 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
182 //
183 // Routes:
184 //  "primary out" -> "Speaker"
185 //  "Built-In Mic" -> "primary input"
186 //  "Telephony Rx" -> "telephony_rx"
187 //  "telephony_tx" -> "Telephony Tx"
188 //  "FM Tuner" -> "fm_tuner"
189 //
190 // Initial port configs:
191 //  * "Speaker" device port: dynamic configuration
192 //  * "Built-In Mic" device port: dynamic configuration
193 //  * "Telephony Tx" device port: dynamic configuration
194 //  * "Telephony Rx" device port: dynamic configuration
195 //  * "FM Tuner" device port: dynamic configuration
196 //
getPrimaryConfiguration()197 std::unique_ptr<Configuration> getPrimaryConfiguration() {
198     static const Configuration configuration = []() {
199         const std::vector<AudioProfile> standardPcmAudioProfiles = {
200                 createProfile(PcmType::INT_16_BIT,
201                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
202                               {8000, 11025, 16000, 32000, 44100, 48000})};
203         Configuration c;
204 
205         // Device ports
206 
207         AudioPort speakerOutDevice =
208                 createPort(c.nextPortId++, "Speaker", 0, false,
209                            createDeviceExt(AudioDeviceType::OUT_SPEAKER,
210                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
211         c.ports.push_back(speakerOutDevice);
212         c.initialConfigs.push_back(
213                 createDynamicPortConfig(speakerOutDevice.id, speakerOutDevice.id, 0, false,
214                                         createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
215 
216         AudioPort micInDevice =
217                 createPort(c.nextPortId++, "Built-In Mic", 0, true,
218                            createDeviceExt(AudioDeviceType::IN_MICROPHONE,
219                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
220         c.ports.push_back(micInDevice);
221         c.initialConfigs.push_back(
222                 createDynamicPortConfig(micInDevice.id, micInDevice.id, 0, true,
223                                         createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
224 
225         AudioPort telephonyTxOutDevice =
226                 createPort(c.nextPortId++, "Telephony Tx", 0, false,
227                            createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0));
228         c.ports.push_back(telephonyTxOutDevice);
229         c.initialConfigs.push_back(
230                 createDynamicPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id, 0, false,
231                                         createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
232 
233         AudioPort telephonyRxInDevice =
234                 createPort(c.nextPortId++, "Telephony Rx", 0, true,
235                            createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0));
236         c.ports.push_back(telephonyRxInDevice);
237         c.initialConfigs.push_back(
238                 createDynamicPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id, 0, true,
239                                         createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
240 
241         AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
242                                                createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
243         c.ports.push_back(fmTunerInDevice);
244         c.initialConfigs.push_back(
245                 createDynamicPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, 0, true,
246                                         createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
247 
248         // Mix ports
249 
250         AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
251                                              makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
252                                              false, createPortMixExt(0, 0));
253         primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
254                                       standardPcmAudioProfiles.begin(),
255                                       standardPcmAudioProfiles.end());
256         c.ports.push_back(primaryOutMix);
257 
258         AudioPort primaryInMix =
259                 createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 1));
260         primaryInMix.profiles.push_back(
261                 createProfile(PcmType::INT_16_BIT,
262                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
263                               {8000, 11025, 16000, 32000, 44100, 48000}));
264         c.ports.push_back(primaryInMix);
265 
266         AudioPort telephonyTxOutMix =
267                 createPort(c.nextPortId++, "telephony_tx", 0, false, createPortMixExt(1, 1));
268         telephonyTxOutMix.profiles.insert(telephonyTxOutMix.profiles.begin(),
269                                           standardPcmAudioProfiles.begin(),
270                                           standardPcmAudioProfiles.end());
271         c.ports.push_back(telephonyTxOutMix);
272 
273         AudioPort telephonyRxInMix =
274                 createPort(c.nextPortId++, "telephony_rx", 0, true, createPortMixExt(0, 1));
275         telephonyRxInMix.profiles.insert(telephonyRxInMix.profiles.begin(),
276                                          standardPcmAudioProfiles.begin(),
277                                          standardPcmAudioProfiles.end());
278         c.ports.push_back(telephonyRxInMix);
279 
280         AudioPort fmTunerInMix =
281                 createPort(c.nextPortId++, "fm_tuner", 0, true, createPortMixExt(0, 1));
282         fmTunerInMix.profiles.insert(fmTunerInMix.profiles.begin(),
283                                      standardPcmAudioProfiles.begin(),
284                                      standardPcmAudioProfiles.end());
285         c.ports.push_back(fmTunerInMix);
286 
287         c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
288         c.routes.push_back(createRoute({micInDevice}, primaryInMix));
289         c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix));
290         c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
291         c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix));
292 
293         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
294 
295         return c;
296     }();
297     return std::make_unique<Configuration>(configuration);
298 }
299 
300 // Note: When transitioning to loading of XML configs, either keep the configuration
301 // of the remote submix sources from this static configuration, or update the XML
302 // config to match it. There are several reasons for that:
303 //   1. The "Remote Submix In" device is listed in the XML config as "attached",
304 //      however in the AIDL scheme its device type has a "virtual" connection.
305 //   2. The canonical r_submix configuration only lists 'STEREO' and '48000',
306 //      however the framework attempts to open streams for other sample rates
307 //      as well. The legacy r_submix implementation allowed that, but libaudiohal@aidl
308 //      will not find a mix port to use. Because of that, list all sample rates that
309 //      the legacy implementation allowed (note that mono was not allowed, the framework
310 //      is expected to upmix mono tracks into stereo if needed).
311 //   3. The legacy implementation had a hard limit on the number of routes (10),
312 //      and this is checked indirectly by AudioPlaybackCaptureTest#testPlaybackCaptureDoS
313 //      CTS test. Instead of hardcoding the number of routes, we can use
314 //      "maxOpen/ActiveStreamCount" to enforce a similar limit. However, the canonical
315 //      XML file lacks this specification.
316 //
317 // Remote Submix configuration:
318 //
319 // Device ports:
320 //  * "Remote Submix Out", OUT_SUBMIX
321 //    - no profiles specified
322 //  * "Remote Submix In", IN_SUBMIX
323 //    - no profiles specified
324 //
325 // Mix ports:
326 //  * "r_submix output", maximum 10 opened streams, maximum 10 active streams
327 //    - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
328 //  * "r_submix input", maximum 10 opened streams, maximum 10 active streams
329 //    - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
330 //
331 // Routes:
332 //  "r_submix output" -> "Remote Submix Out"
333 //  "Remote Submix In" -> "r_submix input"
334 //
getRSubmixConfiguration()335 std::unique_ptr<Configuration> getRSubmixConfiguration() {
336     static const Configuration configuration = []() {
337         Configuration c;
338         const std::vector<AudioProfile> remoteSubmixPcmAudioProfiles{
339                 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
340                               {8000, 11025, 16000, 32000, 44100, 48000})};
341 
342         // Device ports
343 
344         AudioPort rsubmixOutDevice =
345                 createPort(c.nextPortId++, "Remote Submix Out", 0, false,
346                            createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
347                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
348         c.ports.push_back(rsubmixOutDevice);
349         c.connectedProfiles[rsubmixOutDevice.id] = remoteSubmixPcmAudioProfiles;
350 
351         AudioPort rsubmixInDevice =
352                 createPort(c.nextPortId++, "Remote Submix In", 0, true,
353                            createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
354                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
355         c.ports.push_back(rsubmixInDevice);
356         c.connectedProfiles[rsubmixInDevice.id] = remoteSubmixPcmAudioProfiles;
357 
358         // Mix ports
359 
360         AudioPort rsubmixOutMix =
361                 createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(10, 10));
362         rsubmixOutMix.profiles = remoteSubmixPcmAudioProfiles;
363         c.ports.push_back(rsubmixOutMix);
364 
365         AudioPort rsubmixInMix =
366                 createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(10, 10));
367         rsubmixInMix.profiles = remoteSubmixPcmAudioProfiles;
368         c.ports.push_back(rsubmixInMix);
369 
370         c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
371         c.routes.push_back(createRoute({rsubmixInDevice}, rsubmixInMix));
372 
373         return c;
374     }();
375     return std::make_unique<Configuration>(configuration);
376 }
377 
378 // Usb configuration:
379 //
380 // Device ports:
381 //  * "USB Device Out", OUT_DEVICE, CONNECTION_USB
382 //    - no profiles specified
383 //  * "USB Headset Out", OUT_HEADSET, CONNECTION_USB
384 //    - no profiles specified
385 //  * "USB Device In", IN_DEVICE, CONNECTION_USB
386 //    - no profiles specified
387 //  * "USB Headset In", IN_HEADSET, CONNECTION_USB
388 //    - no profiles specified
389 //
390 // Mix ports:
391 //  * "usb_device output", 1 max open, 1 max active stream
392 //    - no profiles specified
393 //  * "usb_device input", 1 max open, 1 max active stream
394 //    - no profiles specified
395 //
396 // Routes:
397 //  * "usb_device output" -> "USB Device Out"
398 //  * "usb_device output" -> "USB Headset Out"
399 //  * "USB Device In", "USB Headset In" -> "usb_device input"
400 //
401 // Profiles for device port connected state (when simulating connections):
402 //  * "USB Device Out", "USB Headset Out":
403 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
404 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
405 //  * "USB Device In", "USB Headset In":
406 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
407 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
408 //
getUsbConfiguration()409 std::unique_ptr<Configuration> getUsbConfiguration() {
410     static const Configuration configuration = []() {
411         const std::vector<AudioProfile> standardPcmAudioProfiles = {
412                 createProfile(PcmType::INT_16_BIT,
413                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
414                                AudioChannelLayout::INDEX_MASK_1, AudioChannelLayout::INDEX_MASK_2},
415                               {44100, 48000}),
416                 createProfile(PcmType::INT_24_BIT,
417                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
418                                AudioChannelLayout::INDEX_MASK_1, AudioChannelLayout::INDEX_MASK_2},
419                               {44100, 48000})};
420         Configuration c;
421 
422         // Device ports
423 
424         AudioPort usbOutDevice =
425                 createPort(c.nextPortId++, "USB Device Out", 0, false,
426                            createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
427                                            AudioDeviceDescription::CONNECTION_USB));
428         c.ports.push_back(usbOutDevice);
429         c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
430 
431         AudioPort usbOutHeadset =
432                 createPort(c.nextPortId++, "USB Headset Out", 0, false,
433                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
434                                            AudioDeviceDescription::CONNECTION_USB));
435         c.ports.push_back(usbOutHeadset);
436         c.connectedProfiles[usbOutHeadset.id] = standardPcmAudioProfiles;
437 
438         AudioPort usbInDevice = createPort(c.nextPortId++, "USB Device In", 0, true,
439                                            createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
440                                                            AudioDeviceDescription::CONNECTION_USB));
441         c.ports.push_back(usbInDevice);
442         c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
443 
444         AudioPort usbInHeadset =
445                 createPort(c.nextPortId++, "USB Headset In", 0, true,
446                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
447                                            AudioDeviceDescription::CONNECTION_USB));
448         c.ports.push_back(usbInHeadset);
449         c.connectedProfiles[usbInHeadset.id] = standardPcmAudioProfiles;
450 
451         // Mix ports
452 
453         AudioPort usbDeviceOutMix =
454                 createPort(c.nextPortId++, "usb_device output", 0, false, createPortMixExt(1, 1));
455         c.ports.push_back(usbDeviceOutMix);
456 
457         AudioPort usbDeviceInMix =
458                 createPort(c.nextPortId++, "usb_device input", 0, true, createPortMixExt(0, 1));
459         c.ports.push_back(usbDeviceInMix);
460 
461         c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutDevice));
462         c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutHeadset));
463         c.routes.push_back(createRoute({usbInDevice, usbInHeadset}, usbDeviceInMix));
464 
465         return c;
466     }();
467     return std::make_unique<Configuration>(configuration);
468 }
469 
470 // Stub configuration:
471 //
472 // Device ports:
473 //  * "Test Out", OUT_AFE_PROXY
474 //    - no profiles specified
475 //  * "Test In", IN_AFE_PROXY
476 //    - no profiles specified
477 //  * "Wired Headset", OUT_HEADSET
478 //    - no profiles specified
479 //  * "Wired Headset Mic", IN_HEADSET
480 //    - no profiles specified
481 //
482 // Mix ports:
483 //  * "test output", 1 max open, 1 max active stream
484 //    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
485 //  * "test fast output", 1 max open, 1 max active stream
486 //    - profile PCM 24-bit; STEREO; 44100, 48000
487 //  * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active
488 //  stream
489 //    - profile MP3; MONO, STEREO; 44100, 48000
490 //  * "test input", 2 max open, 2 max active streams
491 //    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
492 //        8000, 11025, 16000, 22050, 32000, 44100, 48000
493 //
494 // Routes:
495 //  "test output", "test fast output", "test compressed offload" -> "Test Out"
496 //  "test output" -> "Wired Headset"
497 //  "Test In", "Wired Headset Mic" -> "test input"
498 //
499 // Initial port configs:
500 //  * "Test Out" device port: PCM 24-bit; STEREO; 48000
501 //  * "Test In" device port: PCM 24-bit; MONO; 48000
502 //
503 // Profiles for device port connected state (when simulating connections):
504 //  * "Wired Headset": dynamic profiles
505 //  * "Wired Headset Mic": dynamic profiles
506 //
getStubConfiguration()507 std::unique_ptr<Configuration> getStubConfiguration() {
508     static const Configuration configuration = []() {
509         Configuration c;
510 
511         // Device ports
512 
513         AudioPort testOutDevice = createPort(c.nextPortId++, "Test Out", 0, false,
514                                              createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0));
515         c.ports.push_back(testOutDevice);
516         c.initialConfigs.push_back(
517                 createPortConfig(testOutDevice.id, testOutDevice.id, PcmType::INT_24_BIT,
518                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
519                                  createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0)));
520 
521         AudioPort headsetOutDevice =
522                 createPort(c.nextPortId++, "Wired Headset", 0, false,
523                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
524                                            AudioDeviceDescription::CONNECTION_ANALOG));
525         c.ports.push_back(headsetOutDevice);
526 
527         AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
528                                             createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0));
529         c.ports.push_back(testInDevice);
530         c.initialConfigs.push_back(
531                 createPortConfig(testInDevice.id, testInDevice.id, PcmType::INT_24_BIT,
532                                  AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
533                                  createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0)));
534 
535         AudioPort headsetInDevice =
536                 createPort(c.nextPortId++, "Wired Headset Mic", 0, true,
537                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
538                                            AudioDeviceDescription::CONNECTION_ANALOG));
539         c.ports.push_back(headsetInDevice);
540 
541         // Mix ports
542 
543         AudioPort testOutMix =
544                 createPort(c.nextPortId++, "test output", 0, false, createPortMixExt(1, 1));
545         testOutMix.profiles.push_back(
546                 createProfile(PcmType::INT_24_BIT,
547                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
548                               {8000, 11025, 16000, 32000, 44100, 48000}));
549         c.ports.push_back(testOutMix);
550 
551         AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output",
552                                               makeBitPositionFlagMask({AudioOutputFlags::FAST}),
553                                               false, createPortMixExt(1, 1));
554         testFastOutMix.profiles.push_back(createProfile(
555                 PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000}));
556         c.ports.push_back(testFastOutMix);
557 
558         AudioPort compressedOffloadOutMix =
559                 createPort(c.nextPortId++, "test compressed offload",
560                            makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
561                                                     AudioOutputFlags::COMPRESS_OFFLOAD,
562                                                     AudioOutputFlags::NON_BLOCKING}),
563                            false, createPortMixExt(1, 1));
564         compressedOffloadOutMix.profiles.push_back(
565                 createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
566                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
567                               {44100, 48000}));
568         c.ports.push_back(compressedOffloadOutMix);
569 
570         AudioPort testInMix =
571                 createPort(c.nextPortId++, "test input", 0, true, createPortMixExt(2, 2));
572         testInMix.profiles.push_back(
573                 createProfile(PcmType::INT_16_BIT,
574                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
575                                AudioChannelLayout::LAYOUT_FRONT_BACK},
576                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
577         testInMix.profiles.push_back(
578                 createProfile(PcmType::INT_24_BIT,
579                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
580                                AudioChannelLayout::LAYOUT_FRONT_BACK},
581                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
582         c.ports.push_back(testInMix);
583 
584         c.routes.push_back(
585                 createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
586         c.routes.push_back(createRoute({testOutMix}, headsetOutDevice));
587         c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMix));
588 
589         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
590 
591         return c;
592     }();
593     return std::make_unique<Configuration>(configuration);
594 }
595 
596 // Bluetooth configuration:
597 //
598 // Device ports:
599 //  * "BT A2DP Out", OUT_DEVICE, CONNECTION_BT_A2DP
600 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
601 //  * "BT A2DP Headphones", OUT_HEADPHONE, CONNECTION_BT_A2DP
602 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
603 //  * "BT A2DP Speaker", OUT_SPEAKER, CONNECTION_BT_A2DP
604 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
605 //  * "BT Hearing Aid Out", OUT_HEARING_AID, CONNECTION_WIRELESS
606 //    - no profiles specified
607 //
608 // Mix ports:
609 //  * "a2dp output", 1 max open, 1 max active stream
610 //    - no profiles specified
611 //  * "hearing aid output", 1 max open, 1 max active stream
612 //    - profile PCM 16-bit; STEREO; 16000, 24000
613 //
614 // Routes:
615 //  "a2dp output" -> "BT A2DP Out"
616 //  "a2dp output" -> "BT A2DP Headphones"
617 //  "a2dp output" -> "BT A2DP Speaker"
618 //  "hearing aid output" -> "BT Hearing Aid Out"
619 //
620 // Profiles for device port connected state (when simulating connections):
621 //  * "BT A2DP Out", "BT A2DP Headphones", "BT A2DP Speaker":
622 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
623 //  * "BT Hearing Aid Out":
624 //    - profile PCM 16-bit; STEREO; 16000, 24000
625 //
getBluetoothConfiguration()626 std::unique_ptr<Configuration> getBluetoothConfiguration() {
627     static const Configuration configuration = []() {
628         const std::vector<AudioProfile> standardPcmAudioProfiles = {
629                 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
630                               {44100, 48000, 88200, 96000})};
631         const std::vector<AudioProfile> hearingAidAudioProfiles = {createProfile(
632                 PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000})};
633         Configuration c;
634 
635         // Device ports
636         AudioPort btOutDevice =
637                 createPort(c.nextPortId++, "BT A2DP Out", 0, false,
638                            createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
639                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
640         btOutDevice.profiles.insert(btOutDevice.profiles.begin(), standardPcmAudioProfiles.begin(),
641                                     standardPcmAudioProfiles.end());
642         c.ports.push_back(btOutDevice);
643         c.connectedProfiles[btOutDevice.id] = standardPcmAudioProfiles;
644 
645         AudioPort btOutHeadphone =
646                 createPort(c.nextPortId++, "BT A2DP Headphones", 0, false,
647                            createDeviceExt(AudioDeviceType::OUT_HEADPHONE, 0,
648                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
649         btOutHeadphone.profiles.insert(btOutHeadphone.profiles.begin(),
650                                        standardPcmAudioProfiles.begin(),
651                                        standardPcmAudioProfiles.end());
652         c.ports.push_back(btOutHeadphone);
653         c.connectedProfiles[btOutHeadphone.id] = standardPcmAudioProfiles;
654 
655         AudioPort btOutSpeaker =
656                 createPort(c.nextPortId++, "BT A2DP Speaker", 0, false,
657                            createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0,
658                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
659         btOutSpeaker.profiles.insert(btOutSpeaker.profiles.begin(),
660                                      standardPcmAudioProfiles.begin(),
661                                      standardPcmAudioProfiles.end());
662         c.ports.push_back(btOutSpeaker);
663         c.connectedProfiles[btOutSpeaker.id] = standardPcmAudioProfiles;
664 
665         AudioPort btOutHearingAid =
666                 createPort(c.nextPortId++, "BT Hearing Aid Out", 0, false,
667                            createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0,
668                                            AudioDeviceDescription::CONNECTION_WIRELESS));
669         c.ports.push_back(btOutHearingAid);
670         c.connectedProfiles[btOutHearingAid.id] = hearingAidAudioProfiles;
671 
672         // Mix ports
673         AudioPort btOutMix =
674                 createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
675         c.ports.push_back(btOutMix);
676 
677         AudioPort btHearingOutMix =
678                 createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
679         btHearingOutMix.profiles = hearingAidAudioProfiles;
680         c.ports.push_back(btHearingOutMix);
681 
682         c.routes.push_back(createRoute({btOutMix}, btOutDevice));
683         c.routes.push_back(createRoute({btOutMix}, btOutHeadphone));
684         c.routes.push_back(createRoute({btOutMix}, btOutSpeaker));
685         c.routes.push_back(createRoute({btHearingOutMix}, btOutHearingAid));
686 
687         return c;
688     }();
689     return std::make_unique<Configuration>(configuration);
690 }
691 
getConfiguration(Module::Type moduleType)692 std::unique_ptr<Module::Configuration> getConfiguration(Module::Type moduleType) {
693     switch (moduleType) {
694         case Module::Type::DEFAULT:
695             return getPrimaryConfiguration();
696         case Module::Type::R_SUBMIX:
697             return getRSubmixConfiguration();
698         case Module::Type::STUB:
699             return getStubConfiguration();
700         case Module::Type::USB:
701             return getUsbConfiguration();
702         case Module::Type::BLUETOOTH:
703             return getBluetoothConfiguration();
704     }
705 }
706 
707 }  // namespace aidl::android::hardware::audio::core::internal
708